Contract Overview
Balance:
0 DEV
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x737c2b1248397f462ea0453c6cfdf0463d455e67c31132396d55cd67db460e9b | 0x60806040 | 4027980 | 63 days 10 hrs ago | 0xfaae07bac050bee1efc1a589be6629c3775f3272 | IN | Create: ProofChain | 0 DEV | 0.102841619854 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
ProofChain
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "./IOperationalStaking.sol"; import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; contract ProofChain is OwnableUpgradeable { using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set; IOperationalStaking _stakingInterface; // staking contract bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE"); bytes32 public constant BLOCK_SPECIMEN_PRODUCER_ROLE = keccak256("BLOCK_SPECIMEN_PRODUCER_ROLE"); bytes32 public constant AUDITOR_ROLE = keccak256("AUDITOR_ROLE"); uint256 private constant _DIVIDER = 10 ** 18; // 18 decimals used for scaling uint256 private _blockSpecimenQuorum; // The value is represented as a uint <= 10**18. The threshold value will later be divided by 10**18 to represent it as a percentage. e.g.) 10**18 == 100%; 5 * 10**17 == 50%; uint256 private _secondsPerBlock; // average block time on the chain where the ProofChain is deployed uint128 private _blockSpecimenRewardAllocation; // the reward allocated per block hash uint128 private _bspRequiredStake; // how much a validator should have staked in order to run an operator uint64 private _blockSpecimenSessionDuration; // the length of a session in blocks uint64 private _minSubmissionsRequired; // min number of participants who submitted the agreed specimen hash in order for the quorum to be achieved EnumerableSetUpgradeable.Bytes32Set private _roleNames; // set of all role names, this is unused anymore EnumerableSetUpgradeable.AddressSet private _blockSpecimenProducers; // currently enabled block specimen producer operators EnumerableSetUpgradeable.AddressSet private _governors; // governor operators EnumerableSetUpgradeable.AddressSet private _auditors; // auditor operators mapping(address => uint128) public validatorIDs; // maps an operator address to validatorId mapping(uint128 => EnumerableSetUpgradeable.AddressSet) private _validatorOperators; // operator addresses that validator owns mapping(address => bytes32) public operatorRoles; // operator address => role mapping(uint128 => uint128) private _validatorActiveOperatorsCounters; // how many operators are enabled per validator given validator id mapping(uint64 => mapping(uint64 => BlockSpecimenSession)) private _sessions; // chainId => blockHeight mapping(uint64 => ChainData) private _chainData; // by chain id EnumerableSetUpgradeable.AddressSet private _blockResultProducers; // currently enabled block result producer operators mapping(uint64 => mapping(uint64 => BlockSpecimenSession)) private _blockResultSessions; // chainId => blockHeight bytes32 public constant BLOCK_RESULT_PRODUCER_ROLE = keccak256("BLOCK_RESULT_PRODUCER_ROLE"); uint128 private _brpRequiredStake; // how much a validator should have staked in order to run an operator uint128 private _blockResultRewardAllocation; // the reward allocated per block hash mapping(bytes32 => string[]) private _urls; // hash => urls struct ChainData { uint256 blockOnTargetChain; // block number on the chain for which BSP are produced which is mapped to the current chain block uint256 blockOnCurrentChain; // block number on the chain where the ProofChain is deployed. it is mapped to the target chain block uint256 secondsPerBlock; // average block time on the chain for which BSP is generated uint128 allowedThreshold; // block offsett threshold, used to handle minor de-synchronization over time uint128 maxSubmissionsPerBlockHeight; // max number of block hashes allowed to submit per block height uint64 nthBlock; // block divisor } struct BlockHash { mapping(bytes32 => address[]) participants; // specimen hash => operators who submitted the specimen hash bytes32[] specimenHashes; // raw specimen hashes } struct SessionParticipantData { uint128 stake; // stake at the time when an operator submitted the first specimen hash uint128 submissionCounter; // how many specimen hashes an operator has submitted } struct BlockSpecimenSession { mapping(bytes32 => BlockHash) blockHashes; bytes32[] blockHashesRaw; mapping(address => SessionParticipantData) participantsData; // stake and submission counter, pack these together to save gas uint64 sessionDeadline; // the last block when an operator can submit a specimen hash bool requiresAudit; // auditor can arbitrate the session only if this is set to true } event OperatorAdded(address operator, uint128 validatorId, bytes32 role); event OperatorRemoved(address operator); event OperatorEnabled(address operator); event OperatorDisabled(address operator); event BlockSpecimenProductionProofSubmitted( uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 specimenHash, // SHA-256 content-hash of specimen object file; string storageURL, // URL of specimen storage uint128 submittedStake ); event BSPSessionStarted(uint64 indexed chainId, uint64 indexed blockHeight, uint64 deadline); event BRPSessionStarted(uint64 indexed chainId, uint64 indexed blockHeight, uint64 deadline); event BlockSpecimenRewardAwarded(uint64 indexed chainId, uint64 indexed blockHeight, bytes32 indexed blockhash, bytes32 specimenhash); event BlockResultRewardAwarded(uint64 indexed chainId, uint64 indexed blockHeight, bytes32 indexed specimenHash, bytes32 blockResultHash); event BSPQuorumNotReached(uint64 indexed chainId, uint64 blockHeight); event BRPQuorumNotReached(uint64 indexed chainId, uint64 blockHeight); event BlockSpecimenRewardChanged(uint128 newBlockSpecimenRewardAllocation); event MinimumRequiredStakeChanged(uint128 newStakeRequirement); event StakingInterfaceChanged(address newInterfaceAddress); event SpecimenSessionQuorumChanged(uint256 newQuorumThreshold); event SpecimenSessionDurationChanged(uint64 newSessionDuration); event SpecimenSessionMinSubmissionChanged(uint64 minSubmissions); event NthBlockChanged(uint64 indexed chainId, uint64 indexed nthBlock); event MaxSubmissionsPerBlockHeightChanged(uint256 maxSubmissions); event ChainSyncDataChanged(uint64 indexed chainId, uint256 blockOnTargetChain, uint256 blockOnCurrentChain, uint256 secondsPerBlock); event SecondsPerBlockChanged(uint64 indexed secondsPerBlock); event BlockHeightSubmissionThresholdChanged(uint64 indexed chainId, uint64 threshold); event MinimumRequiredBlockResultStakeChanged(uint128 newStakeRequirement); event BlockResultProductionProofSubmitted(uint64 chainId, uint64 blockHeight, bytes32 specimenHash, bytes32 resultHash, string storageURL, uint128 submittedStake); event BlockResultSessionQuorumChanged(uint256 newQuorumThreshold); event BlockSpecimenResultChanged(uint128 newBlockResultRewardAllocation); event BlockResultRewardChanged(uint128 newBlockSpecimenRewardAllocation); modifier onlyGovernor() { require(_governors.contains(msg.sender), "Sender is not GOVERNANCE_ROLE"); _; } /** * Operators will have multiple addresses: the address they submit the proofs from and the address that manages staking and operator instances */ modifier onlyOperatorManager(address operator) { (address validatorAddress, , , ) = _stakingInterface.getValidatorMetadata(validatorIDs[operator]); require(validatorAddress == msg.sender, "Sender is not operator manager"); _; } function initialize(address initialOwner, address stakingContract) public initializer { __Ownable_init(); _governors.add(msg.sender); _roleNames.add(GOVERNANCE_ROLE); _roleNames.add(BLOCK_SPECIMEN_PRODUCER_ROLE); _roleNames.add(AUDITOR_ROLE); setQuorumThreshold(_DIVIDER / 2); // 50% setBlockSpecimenReward(10 ** 14); // 0.0001 setSessionDuration(240); // blocks setMinSubmissionsRequired(2); setStakingInterface(stakingContract); _governors.remove(msg.sender); operatorRoles[initialOwner] = GOVERNANCE_ROLE; _governors.add(initialOwner); emit OperatorAdded(initialOwner, 0, GOVERNANCE_ROLE); } /** * Adds operator on the staking contract */ function addValidator(address validator, uint128 commissionRate) external onlyGovernor { _stakingInterface.addValidator(validator, commissionRate); } /** * Disables the given operator on the staking contract */ function disableValidator(uint128 validatorId, uint256 blockNumber) external onlyGovernor { _stakingInterface.disableValidator(validatorId, blockNumber); } /** * Enables the operator instance. The operators need to call that function before they can start submitting proofs */ function enableBSPOperator(address operator) external onlyOperatorManager(operator) { _enableOperator(operator, BLOCK_SPECIMEN_PRODUCER_ROLE, _blockSpecimenProducers); } /** * Enables the operator instance. The operators need to call that function before they can start submitting proofs */ function enableBRPOperator(address operator) external onlyOperatorManager(operator) { _enableOperator(operator, BLOCK_RESULT_PRODUCER_ROLE, _blockResultProducers); } /** * Enables the operator instance. The operators need to call that function before they can start submitting proofs */ function _enableOperator(address operator, bytes32 role, EnumerableSetUpgradeable.AddressSet storage operators) internal { require(operatorRoles[operator] == role, "Operator does not perform the requested role"); require(!operators.contains(operator), "Operator is already enabled"); uint128 validatorId = validatorIDs[operator]; operators.add(operator); _validatorActiveOperatorsCounters[validatorId]++; // if no operator was enabled we need to enable the validator instance if (_validatorActiveOperatorsCounters[validatorId] == 1) _stakingInterface.enableValidator(validatorId); emit OperatorEnabled(operator); } /** * Disables the operator instance. The operator cannot submit proofs its instance got disabled. * If all addresses of the operator are disabled, then the operator (validator) instance will get disabled on the staking contract */ function disableBSPOperator(address operator) external onlyOperatorManager(operator) { _disableOperator(operator, BLOCK_SPECIMEN_PRODUCER_ROLE, _blockSpecimenProducers); } /** * Disables the operator instance. The operator cannot submit proofs its instance got disabled. * If all addresses of the operator are disabled, then the operator (validator) instance will get disabled on the staking contract */ function disableBRPOperator(address operator) external onlyOperatorManager(operator) { _disableOperator(operator, BLOCK_RESULT_PRODUCER_ROLE, _blockResultProducers); } /** * Disables the operator instance. The operator cannot submit proofs after its instance got disabled. * If all addresses of the operator are disabled, then the operator (validator) instance will get disabled on the staking contract */ function _disableOperator(address operator, bytes32 role, EnumerableSetUpgradeable.AddressSet storage operators) internal { require(operatorRoles[operator] == role, "Operator does not perform the requested role"); require(operators.contains(operator), "Operator is already disabled"); _removeOperatorFromActiveInstances(operator, operators); emit OperatorDisabled(operator); } /** * Adds the given address to the block specimen producers set */ function addBSPOperator(address operator, uint128 validatorId) external onlyGovernor { _addOperator(operator, validatorId, BLOCK_SPECIMEN_PRODUCER_ROLE); } /** * Adds the given address to the block result producers set */ function addBRPOperator(address operator, uint128 validatorId) external onlyGovernor { _addOperator(operator, validatorId, BLOCK_RESULT_PRODUCER_ROLE); } /** * Adds the given address to the given operator role set */ function _addOperator(address operator, uint128 validatorId, bytes32 role) internal { require(operatorRoles[operator] == 0, "Operator already exists"); operatorRoles[operator] = role; validatorIDs[operator] = validatorId; _validatorOperators[validatorId].add(operator); emit OperatorAdded(operator, validatorId, role); } /** * Removes the given address from the block specimen producers set */ function removeBSPOperator(address operator) external onlyGovernor { _removeOperator(operator, BLOCK_SPECIMEN_PRODUCER_ROLE, _blockSpecimenProducers); } /** * Removes the given address from the block specimen producers set */ function removeBRPOperator(address operator) external onlyGovernor { _removeOperator(operator, BLOCK_RESULT_PRODUCER_ROLE, _blockResultProducers); } /** * Removes the given address from the operators set */ function _removeOperator(address operator, bytes32 role, EnumerableSetUpgradeable.AddressSet storage operators) internal { require(operatorRoles[operator] == role, "Operator does not perform the requested role"); if (operators.contains(operator)) _removeOperatorFromActiveInstances(operator, operators); _validatorOperators[validatorIDs[operator]].remove(operator); validatorIDs[operator] = 0; operatorRoles[operator] = 0; emit OperatorRemoved(operator); } /** * Disables the operator instance. * If all addresses of the operator are disabled, then the operator (validator) instance will get disabled on the staking contract */ function _removeOperatorFromActiveInstances(address operator, EnumerableSetUpgradeable.AddressSet storage operators) internal { operators.remove(operator); uint128 validatorId = validatorIDs[operator]; _validatorActiveOperatorsCounters[validatorId]--; // if there are not more enabled operators left we need to disable the validator instance too if (_validatorActiveOperatorsCounters[validatorId] == 0) _stakingInterface.disableValidator(validatorId, block.number); } /** * Adds the given address to the auditors set */ function addAuditor(address auditor) external onlyGovernor { require(operatorRoles[auditor] == 0, "Operator already exists"); operatorRoles[auditor] = AUDITOR_ROLE; _auditors.add(auditor); emit OperatorAdded(auditor, 0, AUDITOR_ROLE); } /** * Removes the given address from the auditors set */ function removeAuditor(address auditor) external onlyGovernor { require(operatorRoles[auditor] == AUDITOR_ROLE, "Operator is not auditor"); operatorRoles[auditor] = 0; _auditors.remove(auditor); emit OperatorRemoved(auditor); } /** * Adds the given address to the governors set */ function addGovernor(address governor) external onlyOwner { require(operatorRoles[governor] == 0, "Operator already exists"); operatorRoles[governor] = GOVERNANCE_ROLE; _governors.add(governor); emit OperatorAdded(governor, 0, GOVERNANCE_ROLE); } /** * Removes the given address from the governors set */ function removeGovernor(address governor) external onlyOwner { require(operatorRoles[governor] == GOVERNANCE_ROLE, "Operator is not governor"); operatorRoles[governor] = 0; _governors.remove(governor); emit OperatorRemoved(governor); } /** * Updates the amount of tokens required to stake in order to be able to submit the proofs */ function setBSPRequiredStake(uint128 newStakeAmount) public onlyGovernor { _bspRequiredStake = newStakeAmount; emit MinimumRequiredStakeChanged(newStakeAmount); } /** * Updates the amount of tokens required to stake in order to be able to submit the proofs */ function setBRPRequiredStake(uint128 newStakeAmount) public onlyGovernor { _brpRequiredStake = newStakeAmount; emit MinimumRequiredBlockResultStakeChanged(newStakeAmount); } /** * Updates the address of the staking contract */ function setStakingInterface(address stakingContractAddress) public onlyGovernor { _stakingInterface = IOperationalStaking(stakingContractAddress); emit StakingInterfaceChanged(stakingContractAddress); } /** * Update the Block Specimen Quorum Threshold. */ function setQuorumThreshold(uint256 quorum) public onlyGovernor { _blockSpecimenQuorum = quorum; emit SpecimenSessionQuorumChanged(quorum); } /** * Update block divisor */ function setNthBlock(uint64 chainId, uint64 n) public onlyGovernor { _chainData[chainId].nthBlock = n; emit NthBlockChanged(chainId, n); } /** * Update the reward allocation per block specimen. */ function setBlockSpecimenReward(uint128 newBlockSpecimenReward) public onlyGovernor { _blockSpecimenRewardAllocation = newBlockSpecimenReward; emit BlockSpecimenRewardChanged(newBlockSpecimenReward); } /** * Update the reward allocation per block specimen. */ function setBlockResultReward(uint128 newBlockResultReward) public onlyGovernor { _blockResultRewardAllocation = newBlockResultReward; emit BlockResultRewardChanged(newBlockResultReward); } /** * Update the duration of a specimen session in blocks */ function setSessionDuration(uint64 newSessionDuration) public onlyGovernor { _blockSpecimenSessionDuration = newSessionDuration; emit SpecimenSessionDurationChanged(newSessionDuration); } /** * Update the minimum # of submissions required in order to reach quorum */ function setMinSubmissionsRequired(uint64 minSubmissions) public onlyGovernor { _minSubmissionsRequired = minSubmissions; emit SpecimenSessionMinSubmissionChanged(minSubmissions); } /** * Update the max # of submissions per operator per block height */ function setMaxSubmissionsPerBlockHeight(uint64 chainId, uint64 maxSubmissions) public onlyGovernor { _chainData[chainId].maxSubmissionsPerBlockHeight = maxSubmissions; emit MaxSubmissionsPerBlockHeightChanged(maxSubmissions); } /** * Update chain sync data */ function setChainSyncData(uint64 chainId, uint256 blockOnTargetChain, uint256 blockOnCurrentChain, uint256 secondsPerBlock) external onlyGovernor { ChainData storage cd = _chainData[chainId]; require(secondsPerBlock > 0, "Seconds per block cannot be 0"); cd.blockOnTargetChain = blockOnTargetChain; cd.blockOnCurrentChain = blockOnCurrentChain; cd.secondsPerBlock = secondsPerBlock; emit ChainSyncDataChanged(chainId, blockOnTargetChain, blockOnCurrentChain, secondsPerBlock); } /** * Update block height submission threshold for live sync */ function setBlockHeightSubmissionsThreshold(uint64 chainId, uint64 threshold) external onlyGovernor { _chainData[chainId].allowedThreshold = threshold; emit BlockHeightSubmissionThresholdChanged(chainId, threshold); } /** * Update seconds per block on the chain where the ProofChain is deployed */ function setSecondsPerBlock(uint64 secondsPerBlock) external onlyGovernor { _secondsPerBlock = secondsPerBlock; emit SecondsPerBlockChanged(secondsPerBlock); } function submitBlockSpecimenProof(uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 specimenHash, string calldata storageURL) external { _submitProof(chainId, blockHeight, blockHash, specimenHash, storageURL, true); } function submitBlockResultProof(uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 specimenHash, string calldata storageURL) external { _submitProof(chainId, blockHeight, blockHash, specimenHash, storageURL, false); } /** * That function exists because submitProof has too many local variables */ function _startSession( uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 specimenHash, ChainData storage cd, BlockSpecimenSession storage session, bool bspSession, SessionParticipantData storage participantsData ) internal { require(!session.requiresAudit, "Session submissions have closed"); uint256 currentBlockOnTargetChain = cd.blockOnTargetChain + (((block.number - cd.blockOnCurrentChain) * _secondsPerBlock) / cd.secondsPerBlock); uint256 lowerBound = currentBlockOnTargetChain >= cd.allowedThreshold ? currentBlockOnTargetChain - cd.allowedThreshold : 0; require(lowerBound <= blockHeight && blockHeight <= currentBlockOnTargetChain + cd.allowedThreshold, "Block height is out of bounds for live sync"); session.sessionDeadline = uint64(block.number + _blockSpecimenSessionDuration); (uint128 baseStake, uint128 delegateStakes) = _stakingInterface.getValidatorCompoundedStakingData(validatorIDs[msg.sender]); require(baseStake >= (bspSession ? _bspRequiredStake : _brpRequiredStake), "Insufficiently staked to submit"); participantsData.stake = baseStake + delegateStakes; session.blockHashesRaw.push(blockHash); BlockHash storage bh = session.blockHashes[blockHash]; bh.specimenHashes.push(specimenHash); bh.participants[specimenHash].push(msg.sender); participantsData.submissionCounter++; // no need to have a separate session started event for BRP or BSP since there is another submit proof event emitted if (bspSession) emit BSPSessionStarted(chainId, blockHeight, session.sessionDeadline); else emit BRPSessionStarted(chainId, blockHeight, session.sessionDeadline); } /** * Block Specimen Producers submit their block specimen proofs using this function. */ function _submitProof(uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 specimenHash, string calldata storageURL, bool bspSession) internal { if (bspSession) require(_blockSpecimenProducers.contains(msg.sender), "Sender is not BLOCK_SPECIMEN_PRODUCER_ROLE"); else require(_blockResultProducers.contains(msg.sender), "Sender is not BLOCK_RESULT_PRODUCER_ROLE"); ChainData storage cd = _chainData[chainId]; require(cd.nthBlock != 0, "Invalid chain ID"); require(blockHeight % cd.nthBlock == 0, "Invalid block height"); BlockSpecimenSession storage session = bspSession ? _sessions[chainId][blockHeight] : _blockResultSessions[chainId][blockHeight]; uint64 sessionDeadline = session.sessionDeadline; SessionParticipantData storage participantsData = session.participantsData[msg.sender]; // if this is the first specimen to be submitted for a block, initialize a new session if (sessionDeadline == 0) { _startSession(chainId, blockHeight, blockHash, specimenHash, cd, session, bspSession, participantsData); } else { require(block.number <= sessionDeadline, "Session submissions have closed"); require(participantsData.submissionCounter < cd.maxSubmissionsPerBlockHeight, "Max submissions limit exceeded"); BlockHash storage bh = session.blockHashes[blockHash]; bytes32[] storage specimenHashes = bh.specimenHashes; if (participantsData.stake != 0) { // check if it was submitted for the same block hash // this should be at most 10 iterations for (uint256 j = 0; j < specimenHashes.length; j++) { address[] storage specimenHashParticipants = bh.participants[specimenHashes[j]]; for (uint256 k = 0; k < specimenHashParticipants.length; k++) require(specimenHashParticipants[k] != msg.sender, "Operator already submitted for the provided block hash"); } } else { (uint128 baseStake, uint128 delegateStakes) = _stakingInterface.getValidatorCompoundedStakingData(validatorIDs[msg.sender]); require(baseStake >= (bspSession ? _bspRequiredStake : _brpRequiredStake), "Insufficiently staked to submit"); participantsData.stake = baseStake + delegateStakes; } address[] storage participants = bh.participants[specimenHash]; if (specimenHashes.length != 0) { if (participants.length == 0) specimenHashes.push(specimenHash); } else { session.blockHashesRaw.push(blockHash); specimenHashes.push(specimenHash); } participants.push(msg.sender); participantsData.submissionCounter++; } _urls[specimenHash].push(storageURL); if (bspSession) emit BlockSpecimenProductionProofSubmitted(chainId, blockHeight, blockHash, specimenHash, storageURL, participantsData.stake); else emit BlockResultProductionProofSubmitted(chainId, blockHeight, blockHash, specimenHash, storageURL, participantsData.stake); } /** * This function is called to check whether the sesion is open for the given chain id and block height */ function isSessionOpen(uint64 chainId, uint64 blockHeight, bool bspSession, address operator) public view returns (bool) { BlockSpecimenSession storage session = bspSession ? _sessions[chainId][blockHeight] : _blockResultSessions[chainId][blockHeight]; uint64 sessionDeadline = session.sessionDeadline; SessionParticipantData storage participantsData = session.participantsData[operator]; // assuming for brp sessions it can only submit once since only one block specimen is finalized right now bool submissionLimitExceeded = bspSession ? participantsData.submissionCounter == _chainData[chainId].maxSubmissionsPerBlockHeight : participantsData.submissionCounter == 1; return (!submissionLimitExceeded && block.number <= sessionDeadline) || (sessionDeadline == 0 && !session.requiresAudit); } /** * This function is called when a quorum of equivalent hashes have been submitted for a Block Specimen Session. */ function finalizeAndRewardSpecimenSession(uint64 chainId, uint64 blockHeight) public { _finalizeAndRewardSession(chainId, blockHeight, true); } /** * This function is called when a quorum of equivalent hashes have been submitted for a Block Specimen Session. */ function finalizeAndRewardBlockResultSession(uint64 chainId, uint64 blockHeight) public { _finalizeAndRewardSession(chainId, blockHeight, false); } /** * This function is called when a quorum of equivalent hashes have been submitted for a Block Specimen Session. */ function _finalizeAndRewardSession(uint64 chainId, uint64 blockHeight, bool bspSession) internal { BlockSpecimenSession storage session = bspSession ? _sessions[chainId][blockHeight] : _blockResultSessions[chainId][blockHeight]; uint64 sessionDeadline = session.sessionDeadline; require(block.number > sessionDeadline, "Session not past deadline"); require(!session.requiresAudit, "Session cannot be finalized"); require(sessionDeadline != 0, "Session not started"); uint256 contributorsN; bytes32 specimenHash; uint256 max; bytes32 agreedBlockHash; bytes32 agreedSpecimenHash; bytes32[] storage blockHashesRaw = session.blockHashesRaw; bytes32 rawBlockHash; // find the block hash and specimen hashes that the quorum agrees on by finding the specimen hash with the highest number of participants for (uint256 i = 0; i < blockHashesRaw.length; i++) { rawBlockHash = blockHashesRaw[i]; BlockHash storage bh = session.blockHashes[rawBlockHash]; for (uint256 j = 0; j < bh.specimenHashes.length; j++) { specimenHash = bh.specimenHashes[j]; uint256 len = bh.participants[specimenHash].length; contributorsN += len; if (len > max) { max = len; agreedBlockHash = rawBlockHash; agreedSpecimenHash = specimenHash; } } } // check if the number of submissions is sufficient and if the quorum is achieved if (_minSubmissionsRequired <= max && (max * _DIVIDER) / contributorsN > _blockSpecimenQuorum) _rewardParticipants(session, chainId, blockHeight, agreedBlockHash, agreedSpecimenHash, bspSession); else { if (bspSession) emit BSPQuorumNotReached(chainId, blockHeight); else emit BRPQuorumNotReached(chainId, blockHeight); } session.requiresAudit = true; // set session deadline to 0 to release gas session.sessionDeadline = 0; } /** * Called by Auditor role when a quorum is not reached. The auditor's submitted hash is * the definitive truth. */ function arbitrateBlockSpecimenSession(uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 definitiveSpecimenHash) public { _arbitrateSession(chainId, blockHeight, blockHash, definitiveSpecimenHash, true); } /** * Called by Auditor role when a quorum is not reached. The auditor's submitted hash is * the definitive truth. */ function arbitrateBlockResultSession(uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 definitiveSpecimenHash) public { _arbitrateSession(chainId, blockHeight, blockHash, definitiveSpecimenHash, false); } /** * Called by Auditor role when a quorum is not reached. The auditor's submitted hash is * the definitive truth. */ function _arbitrateSession(uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 definitiveSpecimenHash, bool bspSession) internal { require(_auditors.contains(msg.sender), "Sender is not AUDITOR_ROLE"); BlockSpecimenSession storage session = bspSession ? _sessions[chainId][blockHeight] : _blockResultSessions[chainId][blockHeight]; require(session.requiresAudit, "Session must be finalized before audit"); _rewardParticipants(session, chainId, blockHeight, blockHash, definitiveSpecimenHash, bspSession); } function _rewardParticipants(BlockSpecimenSession storage session, uint64 chainId, uint64 blockHeight, bytes32 blockHash, bytes32 specimenHash, bool bspSession) internal { address participant; address[] storage participants = session.blockHashes[blockHash].participants[specimenHash]; uint256 len = participants.length; uint128[] memory ids = new uint128[](len); uint128[] memory rewards = new uint128[](len); uint128 totalStake; mapping(address => SessionParticipantData) storage participantsData = session.participantsData; for (uint256 i = 0; i < len; i++) { totalStake += participantsData[participants[i]].stake; } for (uint256 i = 0; i < len; i++) { participant = participants[i]; SessionParticipantData storage pd = participantsData[participant]; ids[i] = validatorIDs[participant]; rewards[i] = uint128((uint256(pd.stake) * uint256(_blockSpecimenRewardAllocation)) / totalStake); // release gas if possible if (pd.submissionCounter == 1) { pd.submissionCounter = 0; pd.stake = 0; } } _stakingInterface.rewardValidators(ids, rewards); if (bspSession) emit BlockSpecimenRewardAwarded(chainId, blockHeight, blockHash, specimenHash); else emit BlockResultRewardAwarded(chainId, blockHeight, blockHash, specimenHash); delete session.blockHashes[blockHash]; // release gas } /** * Returns contract meta data */ function getMetadata() public view returns ( address stakingInterface, uint128 blockSpecimenRewardAllocation, uint128 blockResultRewardAllocation, uint64 blockSpecimenSessionDuration, uint64 minSubmissionsRequired, uint256 blockSpecimenQuorum, uint256 secondsPerBlock ) { return ( address(_stakingInterface), _blockSpecimenRewardAllocation, _blockResultRewardAllocation, _blockSpecimenSessionDuration, _minSubmissionsRequired, _blockSpecimenQuorum, _secondsPerBlock ); } /** * Returns data used for chain sync */ function getChainData( uint64 chainId ) external view returns (uint256 blockOnTargetChain, uint256 blockOnCurrentChain, uint256 secondsPerBlock, uint128 allowedThreshold, uint128 maxSubmissionsPerBlockHeight, uint64 nthBlock) { ChainData memory cd = _chainData[chainId]; return (cd.blockOnTargetChain, cd.blockOnCurrentChain, cd.secondsPerBlock, cd.allowedThreshold, cd.maxSubmissionsPerBlockHeight, cd.nthBlock); } /** * Returns all operator addresses (disabled and enabled) of a given validator */ function getOperators(uint128 validatorId) external view returns (address[] memory) { return _validatorOperators[validatorId].values(); } /** * Returns all enabled operators by role type */ function getAllOperators() external view returns (address[] memory _bsps, address[] memory __governors, address[] memory __auditors, address[] memory _brps) { return (_blockSpecimenProducers.values(), _governors.values(), _auditors.values(), _blockResultProducers.values()); } /** * Returns required stake and enabled block specimen producer operators */ function getBSPRoleData() external view returns (uint128 requiredStake, address[] memory activeMembers) { return (_bspRequiredStake, _blockSpecimenProducers.values()); } /** * Returns required stake and enabled block result producer operators */ function getBRPRoleData() external view returns (uint128 requiredStake, address[] memory activeMembers) { return (_brpRequiredStake, _blockResultProducers.values()); } function getURLS(bytes32 specimenhash) external view returns (string[] memory) { return _urls[specimenhash]; } /** * Returns true if the given operator is enabled. * Returns false if the operator is disabled or does not exist */ function isEnabled(address operator) external view returns (bool) { return _blockSpecimenProducers.contains(operator) || _blockResultProducers.contains(operator); } }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.13; interface IOperationalStaking { function getValidatorMetadata(uint128 validatorId) external view returns ( address _address, uint128 staked, uint128 delegated, uint128 commissionRate ); function getValidatorStakingData(uint128 validatorId) external view returns (uint128 staked, uint128 delegated); function getValidatorCompoundedStakingData(uint128 validatorId) external view returns (uint128 staked, uint128 delegated); function rewardValidators(uint128[] calldata validatorId, uint128[] calldata amount) external; function addValidator(address validator, uint128 commissionRate) external returns (uint256 id); function disableValidator(uint128 validatorId, uint256 blockNumber) external; function enableValidator(uint128 validatorId) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ library EnumerableSetUpgradeable { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"blockHeight","type":"uint64"}],"name":"BRPQuorumNotReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"blockHeight","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"deadline","type":"uint64"}],"name":"BRPSessionStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"blockHeight","type":"uint64"}],"name":"BSPQuorumNotReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"blockHeight","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"deadline","type":"uint64"}],"name":"BSPSessionStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"threshold","type":"uint64"}],"name":"BlockHeightSubmissionThresholdChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"blockHeight","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"specimenHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"resultHash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"storageURL","type":"string"},{"indexed":false,"internalType":"uint128","name":"submittedStake","type":"uint128"}],"name":"BlockResultProductionProofSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"blockHeight","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"specimenHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"blockResultHash","type":"bytes32"}],"name":"BlockResultRewardAwarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"newBlockSpecimenRewardAllocation","type":"uint128"}],"name":"BlockResultRewardChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newQuorumThreshold","type":"uint256"}],"name":"BlockResultSessionQuorumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"blockHeight","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"specimenHash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"storageURL","type":"string"},{"indexed":false,"internalType":"uint128","name":"submittedStake","type":"uint128"}],"name":"BlockSpecimenProductionProofSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"newBlockResultRewardAllocation","type":"uint128"}],"name":"BlockSpecimenResultChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"blockHeight","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"blockhash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"specimenhash","type":"bytes32"}],"name":"BlockSpecimenRewardAwarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"newBlockSpecimenRewardAllocation","type":"uint128"}],"name":"BlockSpecimenRewardChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"blockOnTargetChain","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockOnCurrentChain","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secondsPerBlock","type":"uint256"}],"name":"ChainSyncDataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxSubmissions","type":"uint256"}],"name":"MaxSubmissionsPerBlockHeightChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"newStakeRequirement","type":"uint128"}],"name":"MinimumRequiredBlockResultStakeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"newStakeRequirement","type":"uint128"}],"name":"MinimumRequiredStakeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"nthBlock","type":"uint64"}],"name":"NthBlockChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"uint128","name":"validatorId","type":"uint128"},{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"OperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"OperatorDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"OperatorEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"OperatorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"secondsPerBlock","type":"uint64"}],"name":"SecondsPerBlockChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"newSessionDuration","type":"uint64"}],"name":"SpecimenSessionDurationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"minSubmissions","type":"uint64"}],"name":"SpecimenSessionMinSubmissionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newQuorumThreshold","type":"uint256"}],"name":"SpecimenSessionQuorumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newInterfaceAddress","type":"address"}],"name":"StakingInterfaceChanged","type":"event"},{"inputs":[],"name":"AUDITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BLOCK_RESULT_PRODUCER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BLOCK_SPECIMEN_PRODUCER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNANCE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"auditor","type":"address"}],"name":"addAuditor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint128","name":"validatorId","type":"uint128"}],"name":"addBRPOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint128","name":"validatorId","type":"uint128"}],"name":"addBSPOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"},{"internalType":"uint128","name":"commissionRate","type":"uint128"}],"name":"addValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"blockHeight","type":"uint64"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"definitiveSpecimenHash","type":"bytes32"}],"name":"arbitrateBlockResultSession","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"blockHeight","type":"uint64"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"definitiveSpecimenHash","type":"bytes32"}],"name":"arbitrateBlockSpecimenSession","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"disableBRPOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"disableBSPOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"validatorId","type":"uint128"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"disableValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"enableBRPOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"enableBSPOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"blockHeight","type":"uint64"}],"name":"finalizeAndRewardBlockResultSession","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"blockHeight","type":"uint64"}],"name":"finalizeAndRewardSpecimenSession","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllOperators","outputs":[{"internalType":"address[]","name":"_bsps","type":"address[]"},{"internalType":"address[]","name":"__governors","type":"address[]"},{"internalType":"address[]","name":"__auditors","type":"address[]"},{"internalType":"address[]","name":"_brps","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBRPRoleData","outputs":[{"internalType":"uint128","name":"requiredStake","type":"uint128"},{"internalType":"address[]","name":"activeMembers","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBSPRoleData","outputs":[{"internalType":"uint128","name":"requiredStake","type":"uint128"},{"internalType":"address[]","name":"activeMembers","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"getChainData","outputs":[{"internalType":"uint256","name":"blockOnTargetChain","type":"uint256"},{"internalType":"uint256","name":"blockOnCurrentChain","type":"uint256"},{"internalType":"uint256","name":"secondsPerBlock","type":"uint256"},{"internalType":"uint128","name":"allowedThreshold","type":"uint128"},{"internalType":"uint128","name":"maxSubmissionsPerBlockHeight","type":"uint128"},{"internalType":"uint64","name":"nthBlock","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMetadata","outputs":[{"internalType":"address","name":"stakingInterface","type":"address"},{"internalType":"uint128","name":"blockSpecimenRewardAllocation","type":"uint128"},{"internalType":"uint128","name":"blockResultRewardAllocation","type":"uint128"},{"internalType":"uint64","name":"blockSpecimenSessionDuration","type":"uint64"},{"internalType":"uint64","name":"minSubmissionsRequired","type":"uint64"},{"internalType":"uint256","name":"blockSpecimenQuorum","type":"uint256"},{"internalType":"uint256","name":"secondsPerBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"validatorId","type":"uint128"}],"name":"getOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"specimenhash","type":"bytes32"}],"name":"getURLS","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"stakingContract","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"blockHeight","type":"uint64"},{"internalType":"bool","name":"bspSession","type":"bool"},{"internalType":"address","name":"operator","type":"address"}],"name":"isSessionOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operatorRoles","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"auditor","type":"address"}],"name":"removeAuditor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"removeBRPOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"removeBSPOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newStakeAmount","type":"uint128"}],"name":"setBRPRequiredStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newStakeAmount","type":"uint128"}],"name":"setBSPRequiredStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"threshold","type":"uint64"}],"name":"setBlockHeightSubmissionsThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newBlockResultReward","type":"uint128"}],"name":"setBlockResultReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newBlockSpecimenReward","type":"uint128"}],"name":"setBlockSpecimenReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"blockOnTargetChain","type":"uint256"},{"internalType":"uint256","name":"blockOnCurrentChain","type":"uint256"},{"internalType":"uint256","name":"secondsPerBlock","type":"uint256"}],"name":"setChainSyncData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"maxSubmissions","type":"uint64"}],"name":"setMaxSubmissionsPerBlockHeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"minSubmissions","type":"uint64"}],"name":"setMinSubmissionsRequired","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"n","type":"uint64"}],"name":"setNthBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"setQuorumThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"secondsPerBlock","type":"uint64"}],"name":"setSecondsPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newSessionDuration","type":"uint64"}],"name":"setSessionDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stakingContractAddress","type":"address"}],"name":"setStakingInterface","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"blockHeight","type":"uint64"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"specimenHash","type":"bytes32"},{"internalType":"string","name":"storageURL","type":"string"}],"name":"submitBlockResultProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"blockHeight","type":"uint64"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"specimenHash","type":"bytes32"},{"internalType":"string","name":"storageURL","type":"string"}],"name":"submitBlockSpecimenProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validatorIDs","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50615ca880620000216000396000f3fe608060405234801561001057600080fd5b506004361061034c5760003560e01c806389587f05116101bd578063cc96e413116100f9578063df4112c2116100a2578063e6116cfd1161007c578063e6116cfd14610917578063eecdac881461092a578063f2fde38b1461093d578063f36c8f5c1461095057600080fd5b8063df4112c2146108de578063e3201409146108f1578063e429cef11461090457600080fd5b8063d5839da9116100d3578063d5839da914610893578063d911c632146108b3578063dd36a8d5146108cb57600080fd5b8063cc96e4131461084d578063cf64a01d14610860578063d3a8b2a81461087357600080fd5b80639914628411610166578063ad9e91ee11610140578063ad9e91ee14610801578063c0e745d214610814578063c384678914610827578063c4499cb91461083a57600080fd5b806399146284146107b45780639c49d8ee146107c7578063a2e7e441146107ee57600080fd5b80639015d371116101975780639015d37114610776578063920036b71461079957806393742b56146107a157600080fd5b806389587f05146107285780638da5cb5b1461073b5780638ecd30bc1461076357600080fd5b8063485cc9551161028c57806367585e44116102355780636e1d616e1161020f5780636e1d616e14610648578063715018a61461066f57806372ab8568146106775780637a5b4f591461068a57600080fd5b806367585e44146106025780636ab9d8e8146106155780636b7511cb1461063557600080fd5b80635a5e84f2116102665780635a5e84f2146105c95780635ebdedfa146105dc5780636543413a146105ef57600080fd5b8063485cc955146104b45780635137b8b9146104c757806354cfa69f146104da57600080fd5b80632f01798e116102f957806341c1278d116102d357806341c1278d1461044657806341ca4a551461047b5780634414beeb1461048e5780634524c7e1146104a157600080fd5b80632f01798e1461040d5780633646aded146104205780633c4a25d01461043357600080fd5b80631fd55ae91161032a5780631fd55ae9146103d1578063222388c2146103e75780632c58ed42146103fa57600080fd5b80630d92f4ed1461035157806313e3f452146103a9578063151fd8f3146103be575b600080fd5b61038361035f366004615356565b6072602052600090815260409020546fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6103bc6103b7366004615356565b610977565b005b6103bc6103cc366004615390565b610aed565b6103d9610b05565b6040516103a0929190615487565b6103bc6103f53660046154d8565b610b46565b6103bc610408366004615511565b610beb565b6103bc61041b366004615544565b610ce4565b6103bc61042e366004615356565b610dc8565b6103bc610441366004615356565b610eb1565b61046d7f77ae3b5d012484be69eeed881350adb3189b651fac6e88b31ddff30c833a8b7f81565b6040519081526020016103a0565b6103bc610489366004615356565b611010565b6103bc61049c36600461555f565b61117c565b6103bc6104af3660046155a1565b611190565b6103bc6104c23660046155ba565b61123a565b6103bc6104d53660046155e8565b611575565b61057d6104e8366004615544565b67ffffffffffffffff908116600090815260776020908152604091829020825160c08101845281548082526001830154938201849052600283015494820185905260038301546fffffffffffffffffffffffffffffffff80821660608501819052700100000000000000000000000000000000909204166080840181905260049094015490961660a090920182905295929492565b604080519687526020870195909552938501929092526fffffffffffffffffffffffffffffffff908116606085015216608083015267ffffffffffffffff1660a082015260c0016103a0565b6103bc6105d73660046155e8565b61164f565b6103bc6105ea366004615511565b611729565b6103bc6105fd366004615390565b611735565b6103bc610610366004615511565b611745565b61046d610623366004615356565b60746020526000908152604090205481565b6103bc610643366004615356565b611841565b61046d7f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f581565b6103bc6118e6565b6103bc610685366004615356565b6118fa565b606554606854607b546069546066546067546040805173ffffffffffffffffffffffffffffffffffffffff90971687526fffffffffffffffffffffffffffffffff95861660208801527001000000000000000000000000000000009094049094169285019290925267ffffffffffffffff80821660608601526801000000000000000090910416608084015260a083015260c082015260e0016103a0565b6103bc6107363660046155e8565b611a66565b60335460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103a0565b6103bc610771366004615511565b611b4b565b610789610784366004615356565b611b57565b60405190151581526020016103a0565b6103d9611bb4565b6103bc6107af366004615544565b611bd9565b6103bc6107c2366004615605565b611cc4565b61046d7f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c81565b6103bc6107fc3660046154d8565b611e1f565b6103bc61080f36600461563e565b611f43565b6103bc6108223660046155e8565b612051565b6103bc61083536600461555f565b612136565b61078961084836600461566a565b612144565b6103bc61085b3660046154d8565b6122b6565b6103bc61086e366004615356565b612357565b6108866108813660046155e8565b6123f9565b6040516103a091906156c7565b6108a66108a13660046155a1565b612426565b6040516103a091906156da565b6108bb612512565b6040516103a094939291906157b1565b6103bc6108d9366004615544565b61254e565b6103bc6108ec366004615356565b612600565b6103bc6108ff366004615511565b61276c565b6103bc610912366004615356565b612855565b6103bc610925366004615356565b612a22565b6103bc610938366004615356565b612bbe565b6103bc61094b366004615356565b612ca5565b61046d7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b60655473ffffffffffffffffffffffffffffffffffffffff8281166000908152607260205260408082205490517f87326a0c0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015284939192909116906387326a0c90602401608060405180830381865afa158015610a0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a329190615809565b50919250505073ffffffffffffffffffffffffffffffffffffffff81163314610abc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53656e646572206973206e6f74206f70657261746f72206d616e61676572000060448201526064015b60405180910390fd5b610ae8837f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c606c612d59565b505050565b610afd8686868686866001612eeb565b505050505050565b60685460009060609070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16610b3e606c61384c565b915091509091565b336000908152606f6020526040902054610bbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b610be782827f77ae3b5d012484be69eeed881350adb3189b651fac6e88b31ddff30c833a8b7f613860565b5050565b336000908152606f6020526040902054610c61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b67ffffffffffffffff82811660008181526077602090815260409182902060030180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169486169485179055905192835290917f4e4c0afc3a2b327c2f061f8ff5190a491f1042ba8f292a887bab97840947b7a9910160405180910390a25050565b336000908152606f6020526040902054610d5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b606980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040519081527f94bc488f4d9a985dd5f9d11e8f0a614a62828888eb65b704a90fa852be937549906020015b60405180910390a150565b336000908152606f6020526040902054610e3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f70016f37fc9a299f674d1e3083a27743406649810887ed947a79884b064d2de990602001610dbd565b610eb96139d5565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090205415610f46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610ab3565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090207f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19055610f99606e82613a56565b506040805173ffffffffffffffffffffffffffffffffffffffff83168152600060208201527f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1918101919091527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a4290606001610dbd565b60655473ffffffffffffffffffffffffffffffffffffffff8281166000908152607260205260408082205490517f87326a0c0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015284939192909116906387326a0c90602401608060405180830381865afa1580156110a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110cb9190615809565b50919250505073ffffffffffffffffffffffffffffffffffffffff81163314611150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53656e646572206973206e6f74206f70657261746f72206d616e6167657200006044820152606401610ab3565b610ae8837f77ae3b5d012484be69eeed881350adb3189b651fac6e88b31ddff30c833a8b7f6078613a78565b61118a848484846001613d5a565b50505050565b336000908152606f6020526040902054611206576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b60668190556040518181527eec8eefea39d742ff523b872c1931ff4d509ab873041c5d6e237d5f0fc053f890602001610dbd565b600054610100900460ff161580801561125a5750600054600160ff909116105b806112745750303b158015611274575060005460ff166001145b611300576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610ab3565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561135e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611366613eda565b611371606e33613a56565b5061139d606a7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1613f79565b506113c9606a7f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c613f79565b506113f5606a7f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f5613f79565b5061140c6104af6002670de0b6b3a76400006158bb565b61141b655af3107a4000611a66565b61142560f0610ce4565b61142f6002611bd9565b61143882610dc8565b611443606e33613f85565b5073ffffffffffffffffffffffffffffffffffffffff831660009081526074602052604090207f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19055611497606e84613a56565b506040805173ffffffffffffffffffffffffffffffffffffffff85168152600060208201527f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb18183015290517f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a429181900360600190a18015610ae857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a1505050565b336000908152606f60205260409020546115eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b606880546fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000918416918202179091556040519081527fb6c040bb0324b47cbf9a620cce03b311e24597626a57322173d5d5465f739d2790602001610dbd565b336000908152606f60205260409020546116c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b607b80546fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000918416918202179091556040519081527fa425d7d9b858a4250625446e4504257053202ae93ba0d1dea68dce7ec87a05c590602001610dbd565b610be782826000613fa7565b610afd8686868686866000612eeb565b336000908152606f60205260409020546117bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b67ffffffffffffffff82811660009081526077602090815260409182902060030180546fffffffffffffffffffffffffffffffff16938516700100000000000000000000000000000000810294909417905590519182527f1bca1fb481202bb14258ce1030d54e9e7bafc8b696d96b9eb733826e58a3a030910160405180910390a15050565b336000908152606f60205260409020546118b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b6118e3817f77ae3b5d012484be69eeed881350adb3189b651fac6e88b31ddff30c833a8b7f6078614364565b50565b6118ee6139d5565b6118f86000614524565b565b60655473ffffffffffffffffffffffffffffffffffffffff8281166000908152607260205260408082205490517f87326a0c0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015284939192909116906387326a0c90602401608060405180830381865afa158015611991573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b59190615809565b50919250505073ffffffffffffffffffffffffffffffffffffffff81163314611a3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53656e646572206973206e6f74206f70657261746f72206d616e6167657200006044820152606401610ab3565b610ae8837f77ae3b5d012484be69eeed881350adb3189b651fac6e88b31ddff30c833a8b7f6078612d59565b336000908152606f6020526040902054611adc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b606880547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff83169081179091556040519081527f01eb821dd596243f2f8c5f6c7478e281b855ac12a9f4be2c486cb2778a0bb81e90602001610dbd565b610be782826001613fa7565b73ffffffffffffffffffffffffffffffffffffffff81166000908152606d6020526040812054151580611bae575073ffffffffffffffffffffffffffffffffffffffff821660009081526079602052604090205415155b92915050565b607b546000906060906fffffffffffffffffffffffffffffffff16610b3e607861384c565b336000908152606f6020526040902054611c4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b606980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8416908102919091179091556040519081527f28312bbddd51eea4439db773218c441a4057f6ed285c642a569f1dcdba1cc04790602001610dbd565b336000908152606f6020526040902054611d3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b67ffffffffffffffff8416600090815260776020526040902081611dba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5365636f6e64732070657220626c6f636b2063616e6e6f7420626520300000006044820152606401610ab3565b8381556001810183905560028101829055604080518581526020810185905290810183905267ffffffffffffffff8616907ffd97af399d19e6be9256c99c8e52b1809cdbc4dc96816739612b6fd4e6d940b09060600160405180910390a25050505050565b336000908152606f6020526040902054611e95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b6065546040517fa2e7e44100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526fffffffffffffffffffffffffffffffff841660248301529091169063a2e7e441906044016020604051808303816000875af1158015611f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae891906158cf565b336000908152606f6020526040902054611fb9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b6065546040517fad9e91ee0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff841660048201526024810183905273ffffffffffffffffffffffffffffffffffffffff9091169063ad9e91ee90604401600060405180830381600087803b15801561203d57600080fd5b505af1158015610afd573d6000803e3d6000fd5b336000908152606f60205260409020546120c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b607b80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff83169081179091556040519081527f3c123a1bb22d50819d69fdf807dc3a338b33bb1089acd51636778324836af17d90602001610dbd565b61118a848484846000613d5a565b600080836121775767ffffffffffffffff8087166000908152607a6020908152604080832093891683529290522061219e565b67ffffffffffffffff80871660009081526076602090815260408083209389168352929052205b600381015473ffffffffffffffffffffffffffffffffffffffff85166000908152600283016020526040812092935067ffffffffffffffff90911691908661221057815470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16600114612260565b67ffffffffffffffff89166000908152607760205260409020600301548254700100000000000000000000000000000000918290046fffffffffffffffffffffffffffffffff9081169290910416145b90508015801561227a57508267ffffffffffffffff164311155b806122a9575067ffffffffffffffff83161580156122a95750600384015468010000000000000000900460ff16155b9998505050505050505050565b336000908152606f602052604090205461232c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b610be782827f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c613860565b336000908152606f60205260409020546123cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b6118e3817f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c606c614364565b6fffffffffffffffffffffffffffffffff81166000908152607360205260409020606090611bae9061384c565b6060607c6000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561250757838290600052602060002001805461247a906158e8565b80601f01602080910402602001604051908101604052809291908181526020018280546124a6906158e8565b80156124f35780601f106124c8576101008083540402835291602001916124f3565b820191906000526020600020905b8154815290600101906020018083116124d657829003601f168201915b50505050508152602001906001019061245b565b505050509050919050565b606080606080612522606c61384c565b61252c606e61384c565b612536607061384c565b612540607861384c565b935093509350935090919293565b336000908152606f60205260409020546125c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b67ffffffffffffffff811660678190556040517fcaf46ba335d93b98398af7142ea3e362a6b8e91c57da6bf1e8a704f86374dde090600090a250565b60655473ffffffffffffffffffffffffffffffffffffffff8281166000908152607260205260408082205490517f87326a0c0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015284939192909116906387326a0c90602401608060405180830381865afa158015612697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126bb9190615809565b50919250505073ffffffffffffffffffffffffffffffffffffffff81163314612740576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53656e646572206973206e6f74206f70657261746f72206d616e6167657200006044820152606401610ab3565b610ae8837f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c606c613a78565b336000908152606f60205260409020546127e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b67ffffffffffffffff82811660008181526077602052604080822060040180547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169486169485179055517fbbfa9310306e8a8485d109f8be6b0a808473ce55d2e94b8ca3447c9ddb2854b49190a35050565b336000908152606f60205260409020546128cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090205415612958576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610ab3565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090207f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f590556129ab607082613a56565b506040805173ffffffffffffffffffffffffffffffffffffffff83168152600060208201527f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f5918101919091527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a4290606001610dbd565b336000908152606f6020526040902054612a98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610ab3565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020547f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f514612b46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f72206973206e6f742061756469746f720000000000000000006044820152606401610ab3565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260746020526040812055612b77607082613f85565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f80c0b871b97b595b16a7741c1b06fed0c6f6f558639f18ccbce50724325dc40d90602001610dbd565b612bc66139d5565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb114612c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f70657261746f72206973206e6f7420676f7665726e6f7200000000000000006044820152606401610ab3565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260746020526040812055612b77606e82613f85565b612cad6139d5565b73ffffffffffffffffffffffffffffffffffffffff8116612d50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610ab3565b6118e381614524565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607460205260409020548214612e0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4f70657261746f7220646f6573206e6f7420706572666f726d2074686520726560448201527f7175657374656420726f6c6500000000000000000000000000000000000000006064820152608401610ab3565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600182016020526040902054612e9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4f70657261746f7220697320616c72656164792064697361626c6564000000006044820152606401610ab3565b612ea5838261459b565b60405173ffffffffffffffffffffffffffffffffffffffff841681527f23cd406c7cafe6d88c3f1c1cc16e438745a4236aec25906be2046ca16c36bd1e90602001611568565b8015612f9257336000908152606d6020526040902054612f8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f53656e646572206973206e6f7420424c4f434b5f53504543494d454e5f50524f60448201527f44554345525f524f4c45000000000000000000000000000000000000000000006064820152608401610ab3565b61302e565b3360009081526079602052604090205461302e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f53656e646572206973206e6f7420424c4f434b5f524553554c545f50524f445560448201527f4345525f524f4c450000000000000000000000000000000000000000000000006064820152608401610ab3565b67ffffffffffffffff8088166000908152607760205260408120600481015490921690036130b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f496e76616c696420636861696e204944000000000000000000000000000000006044820152606401610ab3565b60048101546130d19067ffffffffffffffff168861593b565b67ffffffffffffffff1615613142576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f496e76616c696420626c6f636b206865696768740000000000000000000000006044820152606401610ab3565b6000826131745767ffffffffffffffff808a166000908152607a60209081526040808320938c1683529290522061319b565b67ffffffffffffffff808a166000908152607660209081526040808320938c168352929052205b6003810154336000908152600283016020526040812092935067ffffffffffffffff90911691908290036131de576131d98b8b8b8b88888b886146e6565b613757565b8167ffffffffffffffff16431115613252576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53657373696f6e207375626d697373696f6e73206861766520636c6f736564006044820152606401610ab3565b600384015481546fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009283900481169290910416106132ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4d6178207375626d697373696f6e73206c696d697420657863656564656400006044820152606401610ab3565b6000898152602084905260409020815460018201906fffffffffffffffffffffffffffffffff161561346c5760005b815481101561346657600083600001600084848154811061334057613340615962565b90600052602060002001548152602001908152602001600020905060005b8154811015613451573373ffffffffffffffffffffffffffffffffffffffff1682828154811061339057613390615962565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff160361343f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f70657261746f7220616c7265616479207375626d697474656420666f72207460448201527f68652070726f766964656420626c6f636b2068617368000000000000000000006064820152608401610ab3565b8061344981615991565b91505061335e565b5050808061345e90615991565b91505061331d565b50613647565b606554336000908152607260205260408082205490517f4c4a17090000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201529091829173ffffffffffffffffffffffffffffffffffffffff90911690634c4a1709906024016040805180830381865afa158015613500573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352491906159c9565b915091508861354757607b546fffffffffffffffffffffffffffffffff16613571565b60685470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff165b6fffffffffffffffffffffffffffffffff16826fffffffffffffffffffffffffffffffff1610156135fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e73756666696369656e746c79207374616b656420746f207375626d6974006044820152606401610ab3565b61360881836159f8565b85547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9190911617855550505b60008a815260208390526040902081541561368057805460000361367b578154600181018355600083815260209020018b90555b6136ad565b600180870180548083018255600091825260208083209091018f9055845492830185558482529020018b90555b80546001810182556000828152602090200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905583546fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091041684601061371c83615a2c565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505050505b6000888152607c6020908152604082208054600181018255908352912061378091018888615263565b5084156137e55780546040517f57b0cb34d2ff9ed661f8b3c684aaee6cbf0bda5da02f4044205556817fa8e76c916137d8918e918e918e918e918e918e916fffffffffffffffffffffffffffffffff90911690615a5b565b60405180910390a161383f565b80546040517f8741f5bf89731b15f24deb1e84e2bbd381947f009ee378a2daa15ed8abfb948591613836918e918e918e918e918e918e916fffffffffffffffffffffffffffffffff90911690615a5b565b60405180910390a15b5050505050505050505050565b6060600061385983614c6a565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260746020526040902054156138ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610ab3565b73ffffffffffffffffffffffffffffffffffffffff831660009081526074602090815260408083208490556072825280832080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff871690811790915583526073909152902061396f9084613a56565b506040805173ffffffffffffffffffffffffffffffffffffffff851681526fffffffffffffffffffffffffffffffff841660208201529081018290527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a4290606001611568565b60335473ffffffffffffffffffffffffffffffffffffffff1633146118f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ab3565b60006138598373ffffffffffffffffffffffffffffffffffffffff8416614cc6565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607460205260409020548214613b2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4f70657261746f7220646f6573206e6f7420706572666f726d2074686520726560448201527f7175657374656420726f6c6500000000000000000000000000000000000000006064820152608401610ab3565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260018201602052604090205415613bbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4f70657261746f7220697320616c726561647920656e61626c656400000000006044820152606401610ab3565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607260205260409020546fffffffffffffffffffffffffffffffff16613bfd8285613a56565b506fffffffffffffffffffffffffffffffff808216600090815260756020526040812080549092169190613c3083615a2c565b82546101009290920a6fffffffffffffffffffffffffffffffff818102199093169183160217909155828116600090815260756020526040902054166001039050613d0b576065546040517fedff4b610000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff9091169063edff4b6190602401600060405180830381600087803b158015613cf257600080fd5b505af1158015613d06573d6000803e3d6000fd5b505050505b60405173ffffffffffffffffffffffffffffffffffffffff851681527f9e532d260bd7dde07708a6b1f7c64042546243d79bac23514cd74fcfc1a01fe49060200160405180910390a150505050565b33600090815260716020526040902054613dd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f53656e646572206973206e6f742041554449544f525f524f4c450000000000006044820152606401610ab3565b600081613e025767ffffffffffffffff8087166000908152607a60209081526040808320938916835292905220613e29565b67ffffffffffffffff80871660009081526076602090815260408083209389168352929052205b600381015490915068010000000000000000900460ff16613ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53657373696f6e206d7573742062652066696e616c697a6564206265666f726560448201527f20617564697400000000000000000000000000000000000000000000000000006064820152608401610ab3565b610afd818787878787614d15565b600054610100900460ff16613f71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610ab3565b6118f86150d0565b60006138598383614cc6565b60006138598373ffffffffffffffffffffffffffffffffffffffff8416615170565b600081613fd95767ffffffffffffffff8085166000908152607a60209081526040808320938716835292905220614000565b67ffffffffffffffff80851660009081526076602090815260408083209387168352929052205b600381015490915067ffffffffffffffff1643811061407b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f53657373696f6e206e6f74207061737420646561646c696e65000000000000006044820152606401610ab3565b600382015468010000000000000000900460ff16156140f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f53657373696f6e2063616e6e6f742062652066696e616c697a656400000000006044820152606401610ab3565b8067ffffffffffffffff1660000361416a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f53657373696f6e206e6f742073746172746564000000000000000000000000006044820152606401610ab3565b6000808080806001870181805b82548110156142355782818154811061419257614192615962565b6000918252602080832090910154808352908c905260408220909350905b6001820154811015614220578160010181815481106141d1576141d1615962565b6000918252602080832090910154808352908490526040909120549099506141f9818c615aee565b9a508881111561420d578098508497508996505b508061421881615991565b9150506141b0565b5050808061422d90615991565b915050614177565b5060695468010000000000000000900467ffffffffffffffff16851080159061427b57506066548761426f670de0b6b3a764000088615b06565b61427991906158bb565b115b156142935761428e898d8d87878f614d15565b614321565b89156142df5760405167ffffffffffffffff8c811682528d16907f8340aa7a5b37153230f8b64fa66f25c843e5002c60e63a25db6a9195005ccabd9060200160405180910390a2614321565b60405167ffffffffffffffff8c811682528d16907f31d16d882c6405d327fa305ecf0d52b45154868e0828822533fd2547f4b21a759060200160405180910390a25b505050600390950180547fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000016680100000000000000001790555050505050505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607460205260409020548214614418576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4f70657261746f7220646f6573206e6f7420706572666f726d2074686520726560448201527f7175657374656420726f6c6500000000000000000000000000000000000000006064820152608401610ab3565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001820160205260409020541561444f5761444f838261459b565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607260209081526040808320546fffffffffffffffffffffffffffffffff1683526073909152902061449d9084613f85565b5073ffffffffffffffffffffffffffffffffffffffff8316600081815260726020908152604080832080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055607482528083209290925590519182527f80c0b871b97b595b16a7741c1b06fed0c6f6f558639f18ccbce50724325dc40d9101611568565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6145a58183613f85565b5073ffffffffffffffffffffffffffffffffffffffff82166000908152607260209081526040808320546fffffffffffffffffffffffffffffffff908116808552607590935290832080549293929091169161460083615b43565b82546101009290920a6fffffffffffffffffffffffffffffffff81810219909316918316021790915582811660009081526075602052604081205490911690039050610ae8576065546040517fad9e91ee0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff8316600482015243602482015273ffffffffffffffffffffffffffffffffffffffff9091169063ad9e91ee90604401600060405180830381600087803b1580156146c957600080fd5b505af11580156146dd573d6000803e3d6000fd5b50505050505050565b600383015468010000000000000000900460ff1615614761576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53657373696f6e207375626d697373696f6e73206861766520636c6f736564006044820152606401610ab3565b6000846002015460675486600101544361477b9190615b8d565b6147859190615b06565b61478f91906158bb565b855461479b9190615aee565b60038601549091506000906fffffffffffffffffffffffffffffffff168210156147c65760006147e7565b60038601546147e7906fffffffffffffffffffffffffffffffff1683615b8d565b90508867ffffffffffffffff16811115801561482d5750600386015461481f906fffffffffffffffffffffffffffffffff1683615aee565b8967ffffffffffffffff1611155b6148b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f426c6f636b20686569676874206973206f7574206f6620626f756e647320666f60448201527f72206c6976652073796e630000000000000000000000000000000000000000006064820152608401610ab3565b6069546148d09067ffffffffffffffff1643615aee565b6003860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055606554336000908152607260205260408082205490517f4c4a17090000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201529091829173ffffffffffffffffffffffffffffffffffffffff90911690634c4a1709906024016040805180830381865afa15801561499f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149c391906159c9565b91509150856149e657607b546fffffffffffffffffffffffffffffffff16614a10565b60685470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff165b6fffffffffffffffffffffffffffffffff16826fffffffffffffffffffffffffffffffff161015614a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e73756666696369656e746c79207374616b656420746f207375626d6974006044820152606401610ab3565b614aa781836159f8565b85546fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116178655600188810180548083018255600091825260208083209091018e90558d82528a8152604080832080850180548087018255908552838520018f90558e8452808352908320805494850181558352912090910180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790558654909170010000000000000000000000000000000090910416866010614b8483615a2c565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550508615614c1057600388015460405167ffffffffffffffff9182168152818e16918f16907f49caa59dfff8e73f72d249149e72487a67c49cf76549aed997c63963b436c3c29060200160405180910390a3614c5b565b600388015460405167ffffffffffffffff9182168152818e16918f16907f06a773d98907981dde2b75694bea53d9542cb1434717f5c66e699dee821a73249060200160405180910390a35b50505050505050505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015614cba57602002820191906000526020600020905b815481526020019060010190808311614ca6575b50505050509050919050565b6000818152600183016020526040812054614d0d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611bae565b506000611bae565b60008381526020878152604080832085845290915281208054828167ffffffffffffffff811115614d4857614d48615ba4565b604051908082528060200260200182016040528015614d71578160200160208202803683370190505b50905060008267ffffffffffffffff811115614d8f57614d8f615ba4565b604051908082528060200260200182016040528015614db8578160200160208202803683370190505b509050600060028c01815b85811015614e4257816000888381548110614de057614de0615962565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902054614e2e906fffffffffffffffffffffffffffffffff16846159f8565b925080614e3a81615991565b915050614dc3565b5060005b85811015614f6c57868181548110614e6057614e60615962565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff1680835284825260408084206072909352909220548751929a5090916fffffffffffffffffffffffffffffffff90911690879084908110614ec657614ec6615962565b6fffffffffffffffffffffffffffffffff9283166020918202929092010152606854825486831692614efb9281169116615b06565b614f0591906158bb565b858381518110614f1757614f17615962565b6fffffffffffffffffffffffffffffffff92831660209182029290920101528154700100000000000000000000000000000000900416600103614f5957600081555b5080614f6481615991565b915050614e46565b506065546040517f605a501700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063605a501790614fc59087908790600401615c15565b600060405180830381600087803b158015614fdf57600080fd5b505af1158015614ff3573d6000803e3d6000fd5b50505050871561505257898b67ffffffffffffffff168d67ffffffffffffffff167ff05ac779af1ec75a7b2fbe9415b33a67c00294a121786f7ce2eb3f92e4a6424a8c60405161504591815260200190565b60405180910390a46150a3565b898b67ffffffffffffffff168d67ffffffffffffffff167f93dcf9329a330cb95723152c05719560f2fbd50e215c542854b27acc80c9108d8c60405161509a91815260200190565b60405180910390a45b60008a815260208e905260408120906150bf6001830182615305565b505050505050505050505050505050565b600054610100900460ff16615167576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610ab3565b6118f833614524565b60008181526001830160205260408120548015615259576000615194600183615b8d565b85549091506000906151a890600190615b8d565b905081811461520d5760008660000182815481106151c8576151c8615962565b90600052602060002001549050808760000184815481106151eb576151eb615962565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061521e5761521e615c43565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611bae565b6000915050611bae565b82805461526f906158e8565b90600052602060002090601f01602090048101928261529157600085556152f5565b82601f106152c8578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008235161785556152f5565b828001600101855582156152f5579182015b828111156152f55782358255916020019190600101906152da565b5061530192915061531f565b5090565b50805460008255906000526020600020908101906118e391905b5b808211156153015760008155600101615320565b73ffffffffffffffffffffffffffffffffffffffff811681146118e357600080fd5b60006020828403121561536857600080fd5b813561385981615334565b803567ffffffffffffffff8116811461538b57600080fd5b919050565b60008060008060008060a087890312156153a957600080fd5b6153b287615373565b95506153c060208801615373565b94506040870135935060608701359250608087013567ffffffffffffffff808211156153eb57600080fd5b818901915089601f8301126153ff57600080fd5b81358181111561540e57600080fd5b8a602082850101111561542057600080fd5b6020830194508093505050509295509295509295565b600081518084526020808501945080840160005b8381101561547c57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161544a565b509495945050505050565b6fffffffffffffffffffffffffffffffff831681526040602082015260006154b26040830184615436565b949350505050565b6fffffffffffffffffffffffffffffffff811681146118e357600080fd5b600080604083850312156154eb57600080fd5b82356154f681615334565b91506020830135615506816154ba565b809150509250929050565b6000806040838503121561552457600080fd5b61552d83615373565b915061553b60208401615373565b90509250929050565b60006020828403121561555657600080fd5b61385982615373565b6000806000806080858703121561557557600080fd5b61557e85615373565b935061558c60208601615373565b93969395505050506040820135916060013590565b6000602082840312156155b357600080fd5b5035919050565b600080604083850312156155cd57600080fd5b82356155d881615334565b9150602083013561550681615334565b6000602082840312156155fa57600080fd5b8135613859816154ba565b6000806000806080858703121561561b57600080fd5b61562485615373565b966020860135965060408601359560600135945092505050565b6000806040838503121561565157600080fd5b823561565c816154ba565b946020939093013593505050565b6000806000806080858703121561568057600080fd5b61568985615373565b935061569760208601615373565b9250604085013580151581146156ac57600080fd5b915060608501356156bc81615334565b939692955090935050565b6020815260006138596020830184615436565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b838110156157a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089870301855282518051808852835b81811015615755578281018a01518982018b0152890161573a565b8181111561576557848a838b0101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01696909601870195509386019391860191600101615702565b509398975050505050505050565b6080815260006157c46080830187615436565b82810360208401526157d68187615436565b905082810360408401526157ea8186615436565b905082810360608401526157fe8185615436565b979650505050505050565b6000806000806080858703121561581f57600080fd5b845161582a81615334565b602086015190945061583b816154ba565b604086015190935061584c816154ba565b60608601519092506156bc816154ba565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000826158ca576158ca61585d565b500490565b6000602082840312156158e157600080fd5b5051919050565b600181811c908216806158fc57607f821691505b602082108103615935577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600067ffffffffffffffff808416806159565761595661585d565b92169190910692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036159c2576159c261588c565b5060010190565b600080604083850312156159dc57600080fd5b82516159e7816154ba565b6020840151909250615506816154ba565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615a2357615a2361588c565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818103615a5157615a5161588c565b6001019392505050565b600067ffffffffffffffff808a16835280891660208401525086604083015285606083015260c060808301528360c0830152838560e0840137600060e0858401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011683010190506fffffffffffffffffffffffffffffffff831660a083015298975050505050505050565b60008219821115615b0157615b0161588c565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615b3e57615b3e61588c565b500290565b60006fffffffffffffffffffffffffffffffff821680615b6557615b6561588c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b600082821015615b9f57615b9f61588c565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600081518084526020808501945080840160005b8381101561547c5781516fffffffffffffffffffffffffffffffff1687529582019590820190600101615be7565b604081526000615c286040830185615bd3565b8281036020840152615c3a8185615bd3565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea264697066735822122046e0a8f3fd2d2197b633d9c2b5872f97478a01643657c19d9bfe2b2600804a8964736f6c634300080d0033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|