Source Code
Overview
GLMR Balance
GLMR Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 4526209 | 851 days ago | 0 GLMR | ||||
| 4526209 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR | ||||
| 4526206 | 851 days ago | 0 GLMR |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
BlockSpecimenProofChain
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 BlockSpecimenProofChain 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
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
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 SessionStarted(uint64 indexed chainId, uint64 indexed blockHeight, uint64 deadline);
event BlockSpecimenRewardAwarded(uint64 indexed chainId, uint64 indexed blockHeight, bytes32 indexed blockhash, bytes32 specimenhash);
event QuorumNotReached(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);
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
setBlockSpecimenSessionDuration(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);
}
/**
* 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 _removeBSPOperatorFromActiveInstances(address operator) internal {
_blockSpecimenProducers.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);
}
/**
* Enables the operator instance. The operators need to call that function before they can start submitting proofs
*/
function enableBSPOperator(address operator) external onlyOperatorManager(operator) {
require(operatorRoles[operator] == BLOCK_SPECIMEN_PRODUCER_ROLE, "Operator is not BSP");
require(!_blockSpecimenProducers.contains(operator), "Operator is already enabled");
uint128 validatorId = validatorIDs[operator];
_blockSpecimenProducers.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) {
require(operatorRoles[operator] == BLOCK_SPECIMEN_PRODUCER_ROLE, "Operator is not BSP");
require(_blockSpecimenProducers.contains(operator), "Operator is already disabled");
_removeBSPOperatorFromActiveInstances(operator);
emit OperatorDisabled(operator);
}
/**
* Adds the given address to the block specimen producers set
*/
function addBSPOperator(address operator, uint128 validatorId) external onlyGovernor {
require(operatorRoles[operator] == 0, "Operator already exists");
operatorRoles[operator] = BLOCK_SPECIMEN_PRODUCER_ROLE;
validatorIDs[operator] = validatorId;
_validatorOperators[validatorId].add(operator);
emit OperatorAdded(operator, validatorId, BLOCK_SPECIMEN_PRODUCER_ROLE);
}
/**
* Removes the given address from the block specimen producers set
*/
function removeBSPOperator(address operator) external onlyGovernor {
require(operatorRoles[operator] == BLOCK_SPECIMEN_PRODUCER_ROLE, "Operator is not BSP");
if (_blockSpecimenProducers.contains(operator)) _removeBSPOperatorFromActiveInstances(operator);
_validatorOperators[validatorIDs[operator]].remove(operator);
validatorIDs[operator] = 0;
operatorRoles[operator] = 0;
emit OperatorRemoved(operator);
}
/**
* 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 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 duration of a specimen session in blocks
*/
function setBlockSpecimenSessionDuration(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);
}
/**
* Block Specimen Producers submit their block specimen proofs using this function.
*/
function submitBlockSpecimenProof(
uint64 chainId,
uint64 blockHeight,
bytes32 blockHash,
bytes32 specimenHash,
string calldata storageURL
) external {
require(_blockSpecimenProducers.contains(msg.sender), "Sender is not BLOCK_SPECIMEN_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 = _sessions[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) {
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 >= _bspRequiredStake, "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++;
emit SessionStarted(chainId, blockHeight, session.sessionDeadline);
} 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 >= _bspRequiredStake, "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);
emit BlockSpecimenProductionProofSubmitted(chainId, blockHeight, blockHash, specimenHash, storageURL, participantsData.stake);
}
/**
* 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 {
BlockSpecimenSession storage session = _sessions[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);
else emit QuorumNotReached(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 {
require(_auditors.contains(msg.sender), "Sender is not AUDITOR_ROLE");
BlockSpecimenSession storage session = _sessions[chainId][blockHeight];
require(session.requiresAudit, "Session must be finalized before audit");
_rewardParticipants(session, chainId, blockHeight, blockHash, definitiveSpecimenHash);
}
function _rewardParticipants(
BlockSpecimenSession storage session,
uint64 chainId,
uint64 blockHeight,
bytes32 blockHash,
bytes32 specimenHash
) 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);
emit BlockSpecimenRewardAwarded(chainId, blockHeight, blockHash, specimenHash);
delete session.blockHashes[blockHash]; // release gas
}
/**
* Returns contract meta data
*/
function getMetadata()
public
view
returns (
address stakingInterface,
uint128 blockSpecimenRewardAllocation,
uint64 blockSpecimenSessionDuration,
uint64 minSubmissionsRequired,
uint256 blockSpecimenQuorum,
uint256 secondsPerBlock
)
{
return (address(_stakingInterface), _blockSpecimenRewardAllocation, _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 bsp 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
)
{
return (_blockSpecimenProducers.values(), _governors.values(), _auditors.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 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);
}
/**
* Returns IPFS urls where specimens reside
*/
function getURLS(bytes32 specimenhash) external view returns (string[] memory) {
return _urls[specimenhash];
}
/**
* 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,
address operator
) public view returns (bool) {
BlockSpecimenSession storage session = _sessions[chainId][blockHeight];
uint64 sessionDeadline = session.sessionDeadline;
SessionParticipantData storage participantsData = session.participantsData[operator];
bool submissionLimitExceeded = participantsData.submissionCounter == _chainData[chainId].maxSubmissionsPerBlockHeight;
return (!submissionLimitExceeded && block.number <= sessionDeadline) || (sessionDeadline == 0 && !session.requiresAudit);
}
}//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": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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":"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":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":"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":"chainId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"blockHeight","type":"uint64"}],"name":"QuorumNotReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"secondsPerBlock","type":"uint64"}],"name":"SecondsPerBlockChanged","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":"SessionStarted","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_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":"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":"arbitrateBlockSpecimenSession","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":"enableBSPOperator","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[]"}],"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":"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":"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":"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":"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":"newBlockSpecimenReward","type":"uint128"}],"name":"setBlockSpecimenReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newSessionDuration","type":"uint64"}],"name":"setBlockSpecimenSessionDuration","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":"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":"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
608060405234801561001057600080fd5b50615030806100206000396000f3fe608060405234801561001057600080fd5b50600436106102d35760003560e01c80638ecd30bc11610186578063d3a8b2a8116100e3578063e320140911610097578063eecdac8811610071578063eecdac88146107f9578063f2fde38b1461080c578063f36c8f5c1461081f57600080fd5b8063e3201409146107c0578063e429cef1146107d3578063e6116cfd146107e657600080fd5b8063d911c632116100c8578063d911c63214610783578063dd36a8d51461079a578063df4112c2146107ad57600080fd5b8063d3a8b2a814610743578063d5839da91461076357600080fd5b8063a2e7e4411161013a578063ba75fd2f1161011f578063ba75fd2f1461070a578063cc96e4131461071d578063cf64a01d1461073057600080fd5b8063a2e7e441146106e4578063ad9e91ee146106f757600080fd5b806393742b561161016b57806393742b561461069757806399146284146106aa5780639c49d8ee146106bd57600080fd5b80638ecd30bc146106615780639015d3711461067457600080fd5b80635137b8b9116102345780636e1d616e116101e85780637a5b4f59116101cd5780637a5b4f591461056557806389587f05146106265780638da5cb5b1461063957600080fd5b80636e1d616e14610536578063715018a61461055d57600080fd5b806367585e441161021957806367585e44146104e257806367d07ad7146104f55780636ab9d8e81461050857600080fd5b80635137b8b9146103e057806354cfa69f146103f357600080fd5b80633646aded1161028b5780634414beeb116102705780634414beeb146103a75780634524c7e1146103ba578063485cc955146103cd57600080fd5b80633646aded146103815780633c4a25d01461039457600080fd5b8063151fd8f3116102bc578063151fd8f3146103455780631fd55ae9146103585780632c58ed421461036e57600080fd5b80630d92f4ed146102d857806313e3f45214610330575b600080fd5b61030a6102e63660046146fe565b6072602052600090815260409020546fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61034361033e3660046146fe565b610846565b005b610343610353366004614738565b610b02565b610360611844565b60405161032792919061482f565b61034361037c366004614862565b611885565b61034361038f3660046146fe565b611979565b6103436103a23660046146fe565b611a64565b6103436103b5366004614895565b611bc3565b6103436103c83660046148d7565b611d0e565b6103436103db3660046148f0565b611db3565b6103436103ee366004614947565b6120ea565b610496610401366004614964565b67ffffffffffffffff908116600090815260776020908152604091829020825160c08101845281548082526001830154938201849052600283015494820185905260038301546fffffffffffffffffffffffffffffffff80821660608501819052700100000000000000000000000000000000909204166080840181905260049094015490961660a090920182905295929492565b604080519687526020870195909552938501929092526fffffffffffffffffffffffffffffffff908116606085015216608083015267ffffffffffffffff1660a082015260c001610327565b6103436104f0366004614862565b6121bf565b610343610503366004614964565b6122b7565b6105286105163660046146fe565b60746020526000908152604090205481565b604051908152602001610327565b6105287f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f581565b61034361238f565b6105c360655460685460695460665460675473ffffffffffffffffffffffffffffffffffffffff909416946fffffffffffffffffffffffffffffffff9093169367ffffffffffffffff80841694680100000000000000009094041692565b6040805173ffffffffffffffffffffffffffffffffffffffff90971687526fffffffffffffffffffffffffffffffff909516602087015267ffffffffffffffff9384169486019490945291166060840152608083015260a082015260c001610327565b610343610634366004614947565b6123a3565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610327565b61034361066f366004614862565b612483565b6106876106823660046146fe565b6127b6565b6040519015158152602001610327565b6103436106a5366004614964565b6127c9565b6103436106b836600461497f565b6128af565b6105287f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c81565b6103436106f23660046149b8565b612a05565b6103436107053660046149e6565b612b24565b610687610718366004614a12565b612c36565b61034361072b3660046149b8565b612d21565b61034361073e3660046146fe565b612f49565b610756610751366004614947565b613156565b6040516103279190614a59565b6107766107713660046148d7565b613183565b6040516103279190614a6c565b61078b61326f565b60405161032793929190614b43565b6103436107a8366004614964565b61329d565b6103436107bb3660046146fe565b61334a565b6103436107ce366004614862565b61374a565b6103436107e13660046146fe565b61382e565b6103436107f43660046146fe565b6139f6565b6103436108073660046146fe565b613b8d565b61034361081a3660046146fe565b613c74565b6105287f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b60655473ffffffffffffffffffffffffffffffffffffffff8281166000908152607260205260408082205490517f87326a0c0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015284939192909116906387326a0c90602401608060405180830381865afa1580156108dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109019190614b86565b50919250505073ffffffffffffffffffffffffffffffffffffffff8116331461098b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53656e646572206973206e6f74206f70657261746f72206d616e61676572000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152607460205260409020547f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c14610a39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f70657261746f72206973206e6f7420425350000000000000000000000000006044820152606401610982565b610a44606c84613d2b565b610aaa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4f70657261746f7220697320616c72656164792064697361626c6564000000006044820152606401610982565b610ab383613d5d565b60405173ffffffffffffffffffffffffffffffffffffffff841681527f23cd406c7cafe6d88c3f1c1cc16e438745a4236aec25906be2046ca16c36bd1e906020015b60405180910390a1505050565b610b0d606c33613d2b565b610b99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f53656e646572206973206e6f7420424c4f434b5f53504543494d454e5f50524f60448201527f44554345525f524f4c45000000000000000000000000000000000000000000006064820152608401610982565b67ffffffffffffffff808716600090815260776020526040812060048101549092169003610c23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f496e76616c696420636861696e204944000000000000000000000000000000006044820152606401610982565b6004810154610c3c9067ffffffffffffffff1687614c14565b67ffffffffffffffff1615610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f496e76616c696420626c6f636b206865696768740000000000000000000000006044820152606401610982565b67ffffffffffffffff80881660009081526076602090815260408083208a8516845282528083206003810154338552600282019093529083209093919091169182900361127b57600383015468010000000000000000900460ff1615610d6f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53657373696f6e207375626d697373696f6e73206861766520636c6f736564006044820152606401610982565b60008460020154606754866001015443610d899190614c6a565b610d939190614c81565b610d9d9190614cbe565b8554610da99190614cd2565b60038601549091506000906fffffffffffffffffffffffffffffffff16821015610dd4576000610df5565b6003860154610df5906fffffffffffffffffffffffffffffffff1683614c6a565b90508a67ffffffffffffffff168111158015610e3b57506003860154610e2d906fffffffffffffffffffffffffffffffff1683614cd2565b8b67ffffffffffffffff1611155b610ec7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f426c6f636b20686569676874206973206f7574206f6620626f756e647320666f60448201527f72206c6976652073796e630000000000000000000000000000000000000000006064820152608401610982565b606954610ede9067ffffffffffffffff1643614cd2565b6003860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055606554336000908152607260205260408082205490517f4c4a17090000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201529091829173ffffffffffffffffffffffffffffffffffffffff90911690634c4a1709906024016040805180830381865afa158015610fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd19190614cea565b60685491935091506fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091048116908316101561106c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e73756666696369656e746c79207374616b656420746f207375626d6974006044820152606401610982565b6110768183614d19565b8560000160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550866001018c908060018154018082558091505060019003906000526020600020016000909190919091505560008760000160008e81526020019081526020016000209050806001018c90806001815401808255809150506001900390600052602060002001600090919091909150558060000160008d8152602001908152602001600020339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600001601081819054906101000a90046fffffffffffffffffffffffffffffffff16809291906111c590614d4d565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550508d67ffffffffffffffff168f67ffffffffffffffff167f8b1f889addbfa41db5227bae3b091bd5c8b9a9122f874dfe54ba2f75aabe1f4c8a60030160009054906101000a900467ffffffffffffffff16604051611269919067ffffffffffffffff91909116815260200190565b60405180910390a350505050506117b5565b8167ffffffffffffffff164311156112ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53657373696f6e207375626d697373696f6e73206861766520636c6f736564006044820152606401610982565b600384015481546fffffffffffffffffffffffffffffffff70010000000000000000000000000000000092839004811692909104161061138b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4d6178207375626d697373696f6e73206c696d697420657863656564656400006044820152606401610982565b6000888152602084905260409020815460018201906fffffffffffffffffffffffffffffffff16156115095760005b81548110156115035760008360000160008484815481106113dd576113dd614d7c565b90600052602060002001548152602001908152602001600020905060005b81548110156114ee573373ffffffffffffffffffffffffffffffffffffffff1682828154811061142d5761142d614d7c565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16036114dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f70657261746f7220616c7265616479207375626d697474656420666f72207460448201527f68652070726f766964656420626c6f636b2068617368000000000000000000006064820152608401610982565b806114e681614dab565b9150506113fb565b505080806114fb90614dab565b9150506113ba565b506116a5565b606554336000908152607260205260408082205490517f4c4a17090000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201529091829173ffffffffffffffffffffffffffffffffffffffff90911690634c4a1709906024016040805180830381865afa15801561159d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c19190614cea565b60685491935091506fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091048116908316101561165c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e73756666696369656e746c79207374616b656420746f207375626d6974006044820152606401610982565b6116668183614d19565b85547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9190911617855550505b60008981526020839052604090208154156116de5780546000036116d9578154600181018355600083815260209020018a90555b61170b565b600180870180548083018255600091825260208083209091018e9055845492830185558482529020018a90555b80546001810182556000828152602090200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905583546fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091041684601061177a83614d4d565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505050505b60008781526078602090815260408220805460018101825590835291206117de9101878761460b565b5080546040517f57b0cb34d2ff9ed661f8b3c684aaee6cbf0bda5da02f4044205556817fa8e76c91611830918d918d918d918d918d918d916fffffffffffffffffffffffffffffffff90911690614de3565b60405180910390a150505050505050505050565b60685460009060609070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661187d606c613e7b565b915091509091565b611890606e33613d2b565b6118f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff82811660008181526077602090815260409182902060030180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169486169485179055905192835290917f4e4c0afc3a2b327c2f061f8ff5190a491f1042ba8f292a887bab97840947b7a9910160405180910390a25050565b611984606e33613d2b565b6119ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f70016f37fc9a299f674d1e3083a27743406649810887ed947a79884b064d2de9906020015b60405180910390a150565b611a6c613e88565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090205415611af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090207f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19055611b4c606e82613f09565b506040805173ffffffffffffffffffffffffffffffffffffffff83168152600060208201527f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1918101919091527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a4290606001611a59565b611bce607033613d2b565b611c34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f53656e646572206973206e6f742041554449544f525f524f4c450000000000006044820152606401610982565b67ffffffffffffffff8481166000908152607660209081526040808320938716835292905220600381015468010000000000000000900460ff16611cfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53657373696f6e206d7573742062652066696e616c697a6564206265666f726560448201527f20617564697400000000000000000000000000000000000000000000000000006064820152608401610982565b611d078186868686613f2b565b5050505050565b611d19606e33613d2b565b611d7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b60668190556040518181527eec8eefea39d742ff523b872c1931ff4d509ab873041c5d6e237d5f0fc053f890602001611a59565b600054610100900460ff1615808015611dd35750600054600160ff909116105b80611ded5750303b158015611ded575060005460ff166001145b611e79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610982565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ed757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611edf614289565b611eea606e33613f09565b50611f16606a7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1614328565b50611f42606a7f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c614328565b50611f6e606a7f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f5614328565b50611f856103c86002670de0b6b3a7640000614cbe565b611f94655af3107a40006123a3565b611f9e60f06122b7565b611fa860026127c9565b611fb182611979565b611fbc606e33614334565b5073ffffffffffffffffffffffffffffffffffffffff831660009081526074602052604090207f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19055612010606e84613f09565b506040805173ffffffffffffffffffffffffffffffffffffffff85168152600060208201527f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb18183015290517f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a429181900360600190a180156120e557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001610af5565b505050565b6120f5606e33613d2b565b61215b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606880546fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000918416918202179091556040519081527fb6c040bb0324b47cbf9a620cce03b311e24597626a57322173d5d5465f739d2790602001611a59565b6121ca606e33613d2b565b612230576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff82811660009081526077602090815260409182902060030180546fffffffffffffffffffffffffffffffff16938516700100000000000000000000000000000000810294909417905590519182527f1bca1fb481202bb14258ce1030d54e9e7bafc8b696d96b9eb733826e58a3a03091015b60405180910390a15050565b6122c2606e33613d2b565b612328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040519081527f94bc488f4d9a985dd5f9d11e8f0a614a62828888eb65b704a90fa852be93754990602001611a59565b612397613e88565b6123a16000614356565b565b6123ae606e33613d2b565b612414576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606880547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff83169081179091556040519081527f01eb821dd596243f2f8c5f6c7478e281b855ac12a9f4be2c486cb2778a0bb81e90602001611a59565b67ffffffffffffffff808316600090815260766020908152604080832085851684529091529020600381015490911643811061251b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f53657373696f6e206e6f74207061737420646561646c696e65000000000000006044820152606401610982565b600382015468010000000000000000900460ff1615612596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f53657373696f6e2063616e6e6f742062652066696e616c697a656400000000006044820152606401610982565b8067ffffffffffffffff1660000361260a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f53657373696f6e206e6f742073746172746564000000000000000000000000006044820152606401610982565b6000808080806001870181805b82548110156126d55782818154811061263257612632614d7c565b6000918252602080832090910154808352908c905260408220909350905b60018201548110156126c05781600101818154811061267157612671614d7c565b600091825260208083209091015480835290849052604090912054909950612699818c614cd2565b9a50888111156126ad578098508497508996505b50806126b881614dab565b915050612650565b505080806126cd90614dab565b915050612617565b5060695468010000000000000000900467ffffffffffffffff16851080159061271b57506066548761270f670de0b6b3a764000088614c81565b6127199190614cbe565b115b156127325761272d898c8c8787613f2b565b612774565b60405167ffffffffffffffff8b811682528c16907f398fd8f638a7242217f011fd0720a06747f7a85b7d28d7276684b841baea40219060200160405180910390a25b505050600390950180547fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000166801000000000000000017905550505050505050565b60006127c3606c83613d2b565b92915050565b6127d4606e33613d2b565b61283a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8416908102919091179091556040519081527f28312bbddd51eea4439db773218c441a4057f6ed285c642a569f1dcdba1cc04790602001611a59565b6128ba606e33613d2b565b612920576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff84166000908152607760205260409020816129a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5365636f6e64732070657220626c6f636b2063616e6e6f7420626520300000006044820152606401610982565b8381556001810183905560028101829055604080518581526020810185905290810183905267ffffffffffffffff8616907ffd97af399d19e6be9256c99c8e52b1809cdbc4dc96816739612b6fd4e6d940b09060600160405180910390a25050505050565b612a10606e33613d2b565b612a76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b6065546040517fa2e7e44100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526fffffffffffffffffffffffffffffffff841660248301529091169063a2e7e441906044016020604051808303816000875af1158015612b00573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e59190614e76565b612b2f606e33613d2b565b612b95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b6065546040517fad9e91ee0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff841660048201526024810183905273ffffffffffffffffffffffffffffffffffffffff9091169063ad9e91ee906044015b600060405180830381600087803b158015612c1a57600080fd5b505af1158015612c2e573d6000803e3d6000fd5b505050505050565b67ffffffffffffffff83811660008181526076602090815260408083208786168452825280832060038082015473ffffffffffffffffffffffffffffffffffffffff891686526002830185528386209686526077909452918420909101548454939591949290911692700100000000000000000000000000000000918290046fffffffffffffffffffffffffffffffff908116929091041614801581612ce657508267ffffffffffffffff164311155b80612d15575067ffffffffffffffff8316158015612d155750600384015468010000000000000000900460ff16155b98975050505050505050565b612d2c606e33613d2b565b612d92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff821660009081526074602052604090205415612e1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff821660009081526074602090815260408083207f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c90556072825280832080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff8616908117909155835260739091529020612ec19083613f09565b506040805173ffffffffffffffffffffffffffffffffffffffff841681526fffffffffffffffffffffffffffffffff831660208201527f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c918101919091527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a42906060016122ab565b612f54606e33613d2b565b612fba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020547f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c14613068576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f70657261746f72206973206e6f7420425350000000000000000000000000006044820152606401610982565b613073606c82613d2b565b156130815761308181613d5d565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607260209081526040808320546fffffffffffffffffffffffffffffffff168352607390915290206130cf9082614334565b5073ffffffffffffffffffffffffffffffffffffffff8116600081815260726020908152604080832080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055607482528083209290925590519182527f80c0b871b97b595b16a7741c1b06fed0c6f6f558639f18ccbce50724325dc40d9101611a59565b6fffffffffffffffffffffffffffffffff811660009081526073602052604090206060906127c390613e7b565b606060786000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156132645783829060005260206000200180546131d790614e8f565b80601f016020809104026020016040519081016040528092919081815260200182805461320390614e8f565b80156132505780601f1061322557610100808354040283529160200191613250565b820191906000526020600020905b81548152906001019060200180831161323357829003601f168201915b5050505050815260200190600101906131b8565b505050509050919050565b606080606061327e606c613e7b565b613288606e613e7b565b6132926070613e7b565b925092509250909192565b6132a8606e33613d2b565b61330e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff811660678190556040517fcaf46ba335d93b98398af7142ea3e362a6b8e91c57da6bf1e8a704f86374dde090600090a250565b60655473ffffffffffffffffffffffffffffffffffffffff8281166000908152607260205260408082205490517f87326a0c0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015284939192909116906387326a0c90602401608060405180830381865afa1580156133e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134059190614b86565b50919250505073ffffffffffffffffffffffffffffffffffffffff8116331461348a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53656e646572206973206e6f74206f70657261746f72206d616e6167657200006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607460205260409020547f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c14613538576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f70657261746f72206973206e6f7420425350000000000000000000000000006044820152606401610982565b613543606c84613d2b565b156135aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4f70657261746f7220697320616c726561647920656e61626c656400000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607260205260409020546fffffffffffffffffffffffffffffffff166135ed606c85613f09565b506fffffffffffffffffffffffffffffffff80821660009081526075602052604081208054909216919061362083614d4d565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091558281166000908152607560205260409020541660010390506136fb576065546040517fedff4b610000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff9091169063edff4b6190602401600060405180830381600087803b1580156136e257600080fd5b505af11580156136f6573d6000803e3d6000fd5b505050505b60405173ffffffffffffffffffffffffffffffffffffffff851681527f9e532d260bd7dde07708a6b1f7c64042546243d79bac23514cd74fcfc1a01fe49060200160405180910390a150505050565b613755606e33613d2b565b6137bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff82811660008181526077602052604080822060040180547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169486169485179055517fbbfa9310306e8a8485d109f8be6b0a808473ce55d2e94b8ca3447c9ddb2854b49190a35050565b613839606e33613d2b565b61389f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020541561392c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090207f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f5905561397f607082613f09565b506040805173ffffffffffffffffffffffffffffffffffffffff83168152600060208201527f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f5918101919091527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a4290606001611a59565b613a01606e33613d2b565b613a67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020547f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f514613b15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f72206973206e6f742061756469746f720000000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260746020526040812055613b46607082614334565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f80c0b871b97b595b16a7741c1b06fed0c6f6f558639f18ccbce50724325dc40d90602001611a59565b613b95613e88565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb114613c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f70657261746f72206973206e6f7420676f7665726e6f7200000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260746020526040812055613b46606e82614334565b613c7c613e88565b73ffffffffffffffffffffffffffffffffffffffff8116613d1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610982565b613d2881614356565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b9392505050565b613d68606c82614334565b5073ffffffffffffffffffffffffffffffffffffffff81166000908152607260209081526040808320546fffffffffffffffffffffffffffffffff9081168085526075909352908320805492939290911691613dc383614ee2565b82546101009290920a6fffffffffffffffffffffffffffffffff81810219909316918316021790915582811660009081526075602052604081205490911690039050613e77576065546040517fad9e91ee0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff8316600482015243602482015273ffffffffffffffffffffffffffffffffffffffff9091169063ad9e91ee90604401612c00565b5050565b60606000613d56836143cd565b60335473ffffffffffffffffffffffffffffffffffffffff1633146123a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610982565b6000613d568373ffffffffffffffffffffffffffffffffffffffff8416614429565b60008281526020868152604080832084845290915281208054828167ffffffffffffffff811115613f5e57613f5e614f2c565b604051908082528060200260200182016040528015613f87578160200160208202803683370190505b50905060008267ffffffffffffffff811115613fa557613fa5614f2c565b604051908082528060200260200182016040528015613fce578160200160208202803683370190505b509050600060028b01815b8581101561405857816000888381548110613ff657613ff6614d7c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902054614044906fffffffffffffffffffffffffffffffff1684614d19565b92508061405081614dab565b915050613fd9565b5060005b858110156141825786818154811061407657614076614d7c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff1680835284825260408084206072909352909220548751929a5090916fffffffffffffffffffffffffffffffff909116908790849081106140dc576140dc614d7c565b6fffffffffffffffffffffffffffffffff92831660209182029290920101526068548254868316926141119281169116614c81565b61411b9190614cbe565b85838151811061412d5761412d614d7c565b6fffffffffffffffffffffffffffffffff9283166020918202929092010152815470010000000000000000000000000000000090041660010361416f57600081555b508061417a81614dab565b91505061405c565b506065546040517f605a501700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063605a5017906141db9087908790600401614f9d565b600060405180830381600087803b1580156141f557600080fd5b505af1158015614209573d6000803e3d6000fd5b50505050888a67ffffffffffffffff168c67ffffffffffffffff167ff05ac779af1ec75a7b2fbe9415b33a67c00294a121786f7ce2eb3f92e4a6424a8b60405161425591815260200190565b60405180910390a4600089815260208d9052604081209061427960018301826146ad565b5050505050505050505050505050565b600054610100900460ff16614320576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610982565b6123a1614478565b6000613d568383614429565b6000613d568373ffffffffffffffffffffffffffffffffffffffff8416614518565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561441d57602002820191906000526020600020905b815481526020019060010190808311614409575b50505050509050919050565b6000818152600183016020526040812054614470575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556127c3565b5060006127c3565b600054610100900460ff1661450f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610982565b6123a133614356565b6000818152600183016020526040812054801561460157600061453c600183614c6a565b855490915060009061455090600190614c6a565b90508181146145b557600086600001828154811061457057614570614d7c565b906000526020600020015490508087600001848154811061459357614593614d7c565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806145c6576145c6614fcb565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506127c3565b60009150506127c3565b82805461461790614e8f565b90600052602060002090601f016020900481019282614639576000855561469d565b82601f10614670578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082351617855561469d565b8280016001018555821561469d579182015b8281111561469d578235825591602001919060010190614682565b506146a99291506146c7565b5090565b5080546000825590600052602060002090810190613d2891905b5b808211156146a957600081556001016146c8565b73ffffffffffffffffffffffffffffffffffffffff81168114613d2857600080fd5b60006020828403121561471057600080fd5b8135613d56816146dc565b803567ffffffffffffffff8116811461473357600080fd5b919050565b60008060008060008060a0878903121561475157600080fd5b61475a8761471b565b95506147686020880161471b565b94506040870135935060608701359250608087013567ffffffffffffffff8082111561479357600080fd5b818901915089601f8301126147a757600080fd5b8135818111156147b657600080fd5b8a60208285010111156147c857600080fd5b6020830194508093505050509295509295509295565b600081518084526020808501945080840160005b8381101561482457815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016147f2565b509495945050505050565b6fffffffffffffffffffffffffffffffff8316815260406020820152600061485a60408301846147de565b949350505050565b6000806040838503121561487557600080fd5b61487e8361471b565b915061488c6020840161471b565b90509250929050565b600080600080608085870312156148ab57600080fd5b6148b48561471b565b93506148c26020860161471b565b93969395505050506040820135916060013590565b6000602082840312156148e957600080fd5b5035919050565b6000806040838503121561490357600080fd5b823561490e816146dc565b9150602083013561491e816146dc565b809150509250929050565b6fffffffffffffffffffffffffffffffff81168114613d2857600080fd5b60006020828403121561495957600080fd5b8135613d5681614929565b60006020828403121561497657600080fd5b613d568261471b565b6000806000806080858703121561499557600080fd5b61499e8561471b565b966020860135965060408601359560600135945092505050565b600080604083850312156149cb57600080fd5b82356149d6816146dc565b9150602083013561491e81614929565b600080604083850312156149f957600080fd5b8235614a0481614929565b946020939093013593505050565b600080600060608486031215614a2757600080fd5b614a308461471b565b9250614a3e6020850161471b565b91506040840135614a4e816146dc565b809150509250925092565b602081526000613d5660208301846147de565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b83811015614b35577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089870301855282518051808852835b81811015614ae7578281018a01518982018b01528901614acc565b81811115614af757848a838b0101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01696909601870195509386019391860191600101614a94565b509398975050505050505050565b606081526000614b5660608301866147de565b8281036020840152614b6881866147de565b90508281036040840152614b7c81856147de565b9695505050505050565b60008060008060808587031215614b9c57600080fd5b8451614ba7816146dc565b6020860151909450614bb881614929565b6040860151909350614bc981614929565b6060860151909250614bda81614929565b939692955090935050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680614c2f57614c2f614be5565b92169190910692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015614c7c57614c7c614c3b565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614cb957614cb9614c3b565b500290565b600082614ccd57614ccd614be5565b500490565b60008219821115614ce557614ce5614c3b565b500190565b60008060408385031215614cfd57600080fd5b8251614d0881614929565b602084015190925061491e81614929565b60006fffffffffffffffffffffffffffffffff808316818516808303821115614d4457614d44614c3b565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818103614d7257614d72614c3b565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ddc57614ddc614c3b565b5060010190565b600067ffffffffffffffff808a16835280891660208401525086604083015285606083015260c060808301528360c0830152838560e0840137600060e0858401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011683010190506fffffffffffffffffffffffffffffffff831660a083015298975050505050505050565b600060208284031215614e8857600080fd5b5051919050565b600181811c90821680614ea357607f821691505b602082108103614edc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006fffffffffffffffffffffffffffffffff821680614f0457614f04614c3b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600081518084526020808501945080840160005b838110156148245781516fffffffffffffffffffffffffffffffff1687529582019590820190600101614f6f565b604081526000614fb06040830185614f5b565b8281036020840152614fc28185614f5b565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220893a406362eba55f17f068b1bb867ad4acb7b8a04f007b8ef915048dea5447af64736f6c634300080d0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102d35760003560e01c80638ecd30bc11610186578063d3a8b2a8116100e3578063e320140911610097578063eecdac8811610071578063eecdac88146107f9578063f2fde38b1461080c578063f36c8f5c1461081f57600080fd5b8063e3201409146107c0578063e429cef1146107d3578063e6116cfd146107e657600080fd5b8063d911c632116100c8578063d911c63214610783578063dd36a8d51461079a578063df4112c2146107ad57600080fd5b8063d3a8b2a814610743578063d5839da91461076357600080fd5b8063a2e7e4411161013a578063ba75fd2f1161011f578063ba75fd2f1461070a578063cc96e4131461071d578063cf64a01d1461073057600080fd5b8063a2e7e441146106e4578063ad9e91ee146106f757600080fd5b806393742b561161016b57806393742b561461069757806399146284146106aa5780639c49d8ee146106bd57600080fd5b80638ecd30bc146106615780639015d3711461067457600080fd5b80635137b8b9116102345780636e1d616e116101e85780637a5b4f59116101cd5780637a5b4f591461056557806389587f05146106265780638da5cb5b1461063957600080fd5b80636e1d616e14610536578063715018a61461055d57600080fd5b806367585e441161021957806367585e44146104e257806367d07ad7146104f55780636ab9d8e81461050857600080fd5b80635137b8b9146103e057806354cfa69f146103f357600080fd5b80633646aded1161028b5780634414beeb116102705780634414beeb146103a75780634524c7e1146103ba578063485cc955146103cd57600080fd5b80633646aded146103815780633c4a25d01461039457600080fd5b8063151fd8f3116102bc578063151fd8f3146103455780631fd55ae9146103585780632c58ed421461036e57600080fd5b80630d92f4ed146102d857806313e3f45214610330575b600080fd5b61030a6102e63660046146fe565b6072602052600090815260409020546fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61034361033e3660046146fe565b610846565b005b610343610353366004614738565b610b02565b610360611844565b60405161032792919061482f565b61034361037c366004614862565b611885565b61034361038f3660046146fe565b611979565b6103436103a23660046146fe565b611a64565b6103436103b5366004614895565b611bc3565b6103436103c83660046148d7565b611d0e565b6103436103db3660046148f0565b611db3565b6103436103ee366004614947565b6120ea565b610496610401366004614964565b67ffffffffffffffff908116600090815260776020908152604091829020825160c08101845281548082526001830154938201849052600283015494820185905260038301546fffffffffffffffffffffffffffffffff80821660608501819052700100000000000000000000000000000000909204166080840181905260049094015490961660a090920182905295929492565b604080519687526020870195909552938501929092526fffffffffffffffffffffffffffffffff908116606085015216608083015267ffffffffffffffff1660a082015260c001610327565b6103436104f0366004614862565b6121bf565b610343610503366004614964565b6122b7565b6105286105163660046146fe565b60746020526000908152604090205481565b604051908152602001610327565b6105287f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f581565b61034361238f565b6105c360655460685460695460665460675473ffffffffffffffffffffffffffffffffffffffff909416946fffffffffffffffffffffffffffffffff9093169367ffffffffffffffff80841694680100000000000000009094041692565b6040805173ffffffffffffffffffffffffffffffffffffffff90971687526fffffffffffffffffffffffffffffffff909516602087015267ffffffffffffffff9384169486019490945291166060840152608083015260a082015260c001610327565b610343610634366004614947565b6123a3565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610327565b61034361066f366004614862565b612483565b6106876106823660046146fe565b6127b6565b6040519015158152602001610327565b6103436106a5366004614964565b6127c9565b6103436106b836600461497f565b6128af565b6105287f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c81565b6103436106f23660046149b8565b612a05565b6103436107053660046149e6565b612b24565b610687610718366004614a12565b612c36565b61034361072b3660046149b8565b612d21565b61034361073e3660046146fe565b612f49565b610756610751366004614947565b613156565b6040516103279190614a59565b6107766107713660046148d7565b613183565b6040516103279190614a6c565b61078b61326f565b60405161032793929190614b43565b6103436107a8366004614964565b61329d565b6103436107bb3660046146fe565b61334a565b6103436107ce366004614862565b61374a565b6103436107e13660046146fe565b61382e565b6103436107f43660046146fe565b6139f6565b6103436108073660046146fe565b613b8d565b61034361081a3660046146fe565b613c74565b6105287f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b60655473ffffffffffffffffffffffffffffffffffffffff8281166000908152607260205260408082205490517f87326a0c0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015284939192909116906387326a0c90602401608060405180830381865afa1580156108dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109019190614b86565b50919250505073ffffffffffffffffffffffffffffffffffffffff8116331461098b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53656e646572206973206e6f74206f70657261746f72206d616e61676572000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152607460205260409020547f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c14610a39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f70657261746f72206973206e6f7420425350000000000000000000000000006044820152606401610982565b610a44606c84613d2b565b610aaa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4f70657261746f7220697320616c72656164792064697361626c6564000000006044820152606401610982565b610ab383613d5d565b60405173ffffffffffffffffffffffffffffffffffffffff841681527f23cd406c7cafe6d88c3f1c1cc16e438745a4236aec25906be2046ca16c36bd1e906020015b60405180910390a1505050565b610b0d606c33613d2b565b610b99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f53656e646572206973206e6f7420424c4f434b5f53504543494d454e5f50524f60448201527f44554345525f524f4c45000000000000000000000000000000000000000000006064820152608401610982565b67ffffffffffffffff808716600090815260776020526040812060048101549092169003610c23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f496e76616c696420636861696e204944000000000000000000000000000000006044820152606401610982565b6004810154610c3c9067ffffffffffffffff1687614c14565b67ffffffffffffffff1615610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f496e76616c696420626c6f636b206865696768740000000000000000000000006044820152606401610982565b67ffffffffffffffff80881660009081526076602090815260408083208a8516845282528083206003810154338552600282019093529083209093919091169182900361127b57600383015468010000000000000000900460ff1615610d6f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53657373696f6e207375626d697373696f6e73206861766520636c6f736564006044820152606401610982565b60008460020154606754866001015443610d899190614c6a565b610d939190614c81565b610d9d9190614cbe565b8554610da99190614cd2565b60038601549091506000906fffffffffffffffffffffffffffffffff16821015610dd4576000610df5565b6003860154610df5906fffffffffffffffffffffffffffffffff1683614c6a565b90508a67ffffffffffffffff168111158015610e3b57506003860154610e2d906fffffffffffffffffffffffffffffffff1683614cd2565b8b67ffffffffffffffff1611155b610ec7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f426c6f636b20686569676874206973206f7574206f6620626f756e647320666f60448201527f72206c6976652073796e630000000000000000000000000000000000000000006064820152608401610982565b606954610ede9067ffffffffffffffff1643614cd2565b6003860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055606554336000908152607260205260408082205490517f4c4a17090000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201529091829173ffffffffffffffffffffffffffffffffffffffff90911690634c4a1709906024016040805180830381865afa158015610fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd19190614cea565b60685491935091506fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091048116908316101561106c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e73756666696369656e746c79207374616b656420746f207375626d6974006044820152606401610982565b6110768183614d19565b8560000160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550866001018c908060018154018082558091505060019003906000526020600020016000909190919091505560008760000160008e81526020019081526020016000209050806001018c90806001815401808255809150506001900390600052602060002001600090919091909150558060000160008d8152602001908152602001600020339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600001601081819054906101000a90046fffffffffffffffffffffffffffffffff16809291906111c590614d4d565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550508d67ffffffffffffffff168f67ffffffffffffffff167f8b1f889addbfa41db5227bae3b091bd5c8b9a9122f874dfe54ba2f75aabe1f4c8a60030160009054906101000a900467ffffffffffffffff16604051611269919067ffffffffffffffff91909116815260200190565b60405180910390a350505050506117b5565b8167ffffffffffffffff164311156112ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53657373696f6e207375626d697373696f6e73206861766520636c6f736564006044820152606401610982565b600384015481546fffffffffffffffffffffffffffffffff70010000000000000000000000000000000092839004811692909104161061138b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4d6178207375626d697373696f6e73206c696d697420657863656564656400006044820152606401610982565b6000888152602084905260409020815460018201906fffffffffffffffffffffffffffffffff16156115095760005b81548110156115035760008360000160008484815481106113dd576113dd614d7c565b90600052602060002001548152602001908152602001600020905060005b81548110156114ee573373ffffffffffffffffffffffffffffffffffffffff1682828154811061142d5761142d614d7c565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16036114dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f70657261746f7220616c7265616479207375626d697474656420666f72207460448201527f68652070726f766964656420626c6f636b2068617368000000000000000000006064820152608401610982565b806114e681614dab565b9150506113fb565b505080806114fb90614dab565b9150506113ba565b506116a5565b606554336000908152607260205260408082205490517f4c4a17090000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201529091829173ffffffffffffffffffffffffffffffffffffffff90911690634c4a1709906024016040805180830381865afa15801561159d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c19190614cea565b60685491935091506fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091048116908316101561165c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e73756666696369656e746c79207374616b656420746f207375626d6974006044820152606401610982565b6116668183614d19565b85547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9190911617855550505b60008981526020839052604090208154156116de5780546000036116d9578154600181018355600083815260209020018a90555b61170b565b600180870180548083018255600091825260208083209091018e9055845492830185558482529020018a90555b80546001810182556000828152602090200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905583546fffffffffffffffffffffffffffffffff7001000000000000000000000000000000009091041684601061177a83614d4d565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505050505b60008781526078602090815260408220805460018101825590835291206117de9101878761460b565b5080546040517f57b0cb34d2ff9ed661f8b3c684aaee6cbf0bda5da02f4044205556817fa8e76c91611830918d918d918d918d918d918d916fffffffffffffffffffffffffffffffff90911690614de3565b60405180910390a150505050505050505050565b60685460009060609070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661187d606c613e7b565b915091509091565b611890606e33613d2b565b6118f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff82811660008181526077602090815260409182902060030180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169486169485179055905192835290917f4e4c0afc3a2b327c2f061f8ff5190a491f1042ba8f292a887bab97840947b7a9910160405180910390a25050565b611984606e33613d2b565b6119ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f70016f37fc9a299f674d1e3083a27743406649810887ed947a79884b064d2de9906020015b60405180910390a150565b611a6c613e88565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090205415611af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090207f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19055611b4c606e82613f09565b506040805173ffffffffffffffffffffffffffffffffffffffff83168152600060208201527f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1918101919091527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a4290606001611a59565b611bce607033613d2b565b611c34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f53656e646572206973206e6f742041554449544f525f524f4c450000000000006044820152606401610982565b67ffffffffffffffff8481166000908152607660209081526040808320938716835292905220600381015468010000000000000000900460ff16611cfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53657373696f6e206d7573742062652066696e616c697a6564206265666f726560448201527f20617564697400000000000000000000000000000000000000000000000000006064820152608401610982565b611d078186868686613f2b565b5050505050565b611d19606e33613d2b565b611d7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b60668190556040518181527eec8eefea39d742ff523b872c1931ff4d509ab873041c5d6e237d5f0fc053f890602001611a59565b600054610100900460ff1615808015611dd35750600054600160ff909116105b80611ded5750303b158015611ded575060005460ff166001145b611e79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610982565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ed757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611edf614289565b611eea606e33613f09565b50611f16606a7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1614328565b50611f42606a7f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c614328565b50611f6e606a7f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f5614328565b50611f856103c86002670de0b6b3a7640000614cbe565b611f94655af3107a40006123a3565b611f9e60f06122b7565b611fa860026127c9565b611fb182611979565b611fbc606e33614334565b5073ffffffffffffffffffffffffffffffffffffffff831660009081526074602052604090207f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19055612010606e84613f09565b506040805173ffffffffffffffffffffffffffffffffffffffff85168152600060208201527f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb18183015290517f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a429181900360600190a180156120e557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001610af5565b505050565b6120f5606e33613d2b565b61215b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606880546fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000918416918202179091556040519081527fb6c040bb0324b47cbf9a620cce03b311e24597626a57322173d5d5465f739d2790602001611a59565b6121ca606e33613d2b565b612230576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff82811660009081526077602090815260409182902060030180546fffffffffffffffffffffffffffffffff16938516700100000000000000000000000000000000810294909417905590519182527f1bca1fb481202bb14258ce1030d54e9e7bafc8b696d96b9eb733826e58a3a03091015b60405180910390a15050565b6122c2606e33613d2b565b612328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040519081527f94bc488f4d9a985dd5f9d11e8f0a614a62828888eb65b704a90fa852be93754990602001611a59565b612397613e88565b6123a16000614356565b565b6123ae606e33613d2b565b612414576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606880547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff83169081179091556040519081527f01eb821dd596243f2f8c5f6c7478e281b855ac12a9f4be2c486cb2778a0bb81e90602001611a59565b67ffffffffffffffff808316600090815260766020908152604080832085851684529091529020600381015490911643811061251b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f53657373696f6e206e6f74207061737420646561646c696e65000000000000006044820152606401610982565b600382015468010000000000000000900460ff1615612596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f53657373696f6e2063616e6e6f742062652066696e616c697a656400000000006044820152606401610982565b8067ffffffffffffffff1660000361260a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f53657373696f6e206e6f742073746172746564000000000000000000000000006044820152606401610982565b6000808080806001870181805b82548110156126d55782818154811061263257612632614d7c565b6000918252602080832090910154808352908c905260408220909350905b60018201548110156126c05781600101818154811061267157612671614d7c565b600091825260208083209091015480835290849052604090912054909950612699818c614cd2565b9a50888111156126ad578098508497508996505b50806126b881614dab565b915050612650565b505080806126cd90614dab565b915050612617565b5060695468010000000000000000900467ffffffffffffffff16851080159061271b57506066548761270f670de0b6b3a764000088614c81565b6127199190614cbe565b115b156127325761272d898c8c8787613f2b565b612774565b60405167ffffffffffffffff8b811682528c16907f398fd8f638a7242217f011fd0720a06747f7a85b7d28d7276684b841baea40219060200160405180910390a25b505050600390950180547fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000166801000000000000000017905550505050505050565b60006127c3606c83613d2b565b92915050565b6127d4606e33613d2b565b61283a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b606980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8416908102919091179091556040519081527f28312bbddd51eea4439db773218c441a4057f6ed285c642a569f1dcdba1cc04790602001611a59565b6128ba606e33613d2b565b612920576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff84166000908152607760205260409020816129a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5365636f6e64732070657220626c6f636b2063616e6e6f7420626520300000006044820152606401610982565b8381556001810183905560028101829055604080518581526020810185905290810183905267ffffffffffffffff8616907ffd97af399d19e6be9256c99c8e52b1809cdbc4dc96816739612b6fd4e6d940b09060600160405180910390a25050505050565b612a10606e33613d2b565b612a76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b6065546040517fa2e7e44100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526fffffffffffffffffffffffffffffffff841660248301529091169063a2e7e441906044016020604051808303816000875af1158015612b00573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e59190614e76565b612b2f606e33613d2b565b612b95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b6065546040517fad9e91ee0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff841660048201526024810183905273ffffffffffffffffffffffffffffffffffffffff9091169063ad9e91ee906044015b600060405180830381600087803b158015612c1a57600080fd5b505af1158015612c2e573d6000803e3d6000fd5b505050505050565b67ffffffffffffffff83811660008181526076602090815260408083208786168452825280832060038082015473ffffffffffffffffffffffffffffffffffffffff891686526002830185528386209686526077909452918420909101548454939591949290911692700100000000000000000000000000000000918290046fffffffffffffffffffffffffffffffff908116929091041614801581612ce657508267ffffffffffffffff164311155b80612d15575067ffffffffffffffff8316158015612d155750600384015468010000000000000000900460ff16155b98975050505050505050565b612d2c606e33613d2b565b612d92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff821660009081526074602052604090205415612e1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff821660009081526074602090815260408083207f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c90556072825280832080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff8616908117909155835260739091529020612ec19083613f09565b506040805173ffffffffffffffffffffffffffffffffffffffff841681526fffffffffffffffffffffffffffffffff831660208201527f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c918101919091527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a42906060016122ab565b612f54606e33613d2b565b612fba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020547f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c14613068576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f70657261746f72206973206e6f7420425350000000000000000000000000006044820152606401610982565b613073606c82613d2b565b156130815761308181613d5d565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607260209081526040808320546fffffffffffffffffffffffffffffffff168352607390915290206130cf9082614334565b5073ffffffffffffffffffffffffffffffffffffffff8116600081815260726020908152604080832080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055607482528083209290925590519182527f80c0b871b97b595b16a7741c1b06fed0c6f6f558639f18ccbce50724325dc40d9101611a59565b6fffffffffffffffffffffffffffffffff811660009081526073602052604090206060906127c390613e7b565b606060786000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156132645783829060005260206000200180546131d790614e8f565b80601f016020809104026020016040519081016040528092919081815260200182805461320390614e8f565b80156132505780601f1061322557610100808354040283529160200191613250565b820191906000526020600020905b81548152906001019060200180831161323357829003601f168201915b5050505050815260200190600101906131b8565b505050509050919050565b606080606061327e606c613e7b565b613288606e613e7b565b6132926070613e7b565b925092509250909192565b6132a8606e33613d2b565b61330e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff811660678190556040517fcaf46ba335d93b98398af7142ea3e362a6b8e91c57da6bf1e8a704f86374dde090600090a250565b60655473ffffffffffffffffffffffffffffffffffffffff8281166000908152607260205260408082205490517f87326a0c0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015284939192909116906387326a0c90602401608060405180830381865afa1580156133e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134059190614b86565b50919250505073ffffffffffffffffffffffffffffffffffffffff8116331461348a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53656e646572206973206e6f74206f70657261746f72206d616e6167657200006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607460205260409020547f98d0bb2de1c65f6d2cbc3401e3d5d5086bfe815cb57e521dafd0ebdbef6ee85c14613538576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f70657261746f72206973206e6f7420425350000000000000000000000000006044820152606401610982565b613543606c84613d2b565b156135aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4f70657261746f7220697320616c726561647920656e61626c656400000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff83166000908152607260205260409020546fffffffffffffffffffffffffffffffff166135ed606c85613f09565b506fffffffffffffffffffffffffffffffff80821660009081526075602052604081208054909216919061362083614d4d565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091558281166000908152607560205260409020541660010390506136fb576065546040517fedff4b610000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff9091169063edff4b6190602401600060405180830381600087803b1580156136e257600080fd5b505af11580156136f6573d6000803e3d6000fd5b505050505b60405173ffffffffffffffffffffffffffffffffffffffff851681527f9e532d260bd7dde07708a6b1f7c64042546243d79bac23514cd74fcfc1a01fe49060200160405180910390a150505050565b613755606e33613d2b565b6137bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b67ffffffffffffffff82811660008181526077602052604080822060040180547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169486169485179055517fbbfa9310306e8a8485d109f8be6b0a808473ce55d2e94b8ca3447c9ddb2854b49190a35050565b613839606e33613d2b565b61389f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020541561392c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f7220616c7265616479206578697374730000000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff811660009081526074602052604090207f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f5905561397f607082613f09565b506040805173ffffffffffffffffffffffffffffffffffffffff83168152600060208201527f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f5918101919091527f797ca55fc7be0f65c71f10996f7a16f801094f8ae3811874afc5a39730772a4290606001611a59565b613a01606e33613d2b565b613a67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f53656e646572206973206e6f7420474f5645524e414e43455f524f4c450000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020547f59a1c48e5837ad7a7f3dcedcbe129bf3249ec4fbf651fd4f5e2600ead39fe2f514613b15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4f70657261746f72206973206e6f742061756469746f720000000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260746020526040812055613b46607082614334565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f80c0b871b97b595b16a7741c1b06fed0c6f6f558639f18ccbce50724325dc40d90602001611a59565b613b95613e88565b73ffffffffffffffffffffffffffffffffffffffff81166000908152607460205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb114613c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f70657261746f72206973206e6f7420676f7665726e6f7200000000000000006044820152606401610982565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260746020526040812055613b46606e82614334565b613c7c613e88565b73ffffffffffffffffffffffffffffffffffffffff8116613d1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610982565b613d2881614356565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b9392505050565b613d68606c82614334565b5073ffffffffffffffffffffffffffffffffffffffff81166000908152607260209081526040808320546fffffffffffffffffffffffffffffffff9081168085526075909352908320805492939290911691613dc383614ee2565b82546101009290920a6fffffffffffffffffffffffffffffffff81810219909316918316021790915582811660009081526075602052604081205490911690039050613e77576065546040517fad9e91ee0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff8316600482015243602482015273ffffffffffffffffffffffffffffffffffffffff9091169063ad9e91ee90604401612c00565b5050565b60606000613d56836143cd565b60335473ffffffffffffffffffffffffffffffffffffffff1633146123a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610982565b6000613d568373ffffffffffffffffffffffffffffffffffffffff8416614429565b60008281526020868152604080832084845290915281208054828167ffffffffffffffff811115613f5e57613f5e614f2c565b604051908082528060200260200182016040528015613f87578160200160208202803683370190505b50905060008267ffffffffffffffff811115613fa557613fa5614f2c565b604051908082528060200260200182016040528015613fce578160200160208202803683370190505b509050600060028b01815b8581101561405857816000888381548110613ff657613ff6614d7c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902054614044906fffffffffffffffffffffffffffffffff1684614d19565b92508061405081614dab565b915050613fd9565b5060005b858110156141825786818154811061407657614076614d7c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff1680835284825260408084206072909352909220548751929a5090916fffffffffffffffffffffffffffffffff909116908790849081106140dc576140dc614d7c565b6fffffffffffffffffffffffffffffffff92831660209182029290920101526068548254868316926141119281169116614c81565b61411b9190614cbe565b85838151811061412d5761412d614d7c565b6fffffffffffffffffffffffffffffffff9283166020918202929092010152815470010000000000000000000000000000000090041660010361416f57600081555b508061417a81614dab565b91505061405c565b506065546040517f605a501700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063605a5017906141db9087908790600401614f9d565b600060405180830381600087803b1580156141f557600080fd5b505af1158015614209573d6000803e3d6000fd5b50505050888a67ffffffffffffffff168c67ffffffffffffffff167ff05ac779af1ec75a7b2fbe9415b33a67c00294a121786f7ce2eb3f92e4a6424a8b60405161425591815260200190565b60405180910390a4600089815260208d9052604081209061427960018301826146ad565b5050505050505050505050505050565b600054610100900460ff16614320576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610982565b6123a1614478565b6000613d568383614429565b6000613d568373ffffffffffffffffffffffffffffffffffffffff8416614518565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561441d57602002820191906000526020600020905b815481526020019060010190808311614409575b50505050509050919050565b6000818152600183016020526040812054614470575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556127c3565b5060006127c3565b600054610100900460ff1661450f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610982565b6123a133614356565b6000818152600183016020526040812054801561460157600061453c600183614c6a565b855490915060009061455090600190614c6a565b90508181146145b557600086600001828154811061457057614570614d7c565b906000526020600020015490508087600001848154811061459357614593614d7c565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806145c6576145c6614fcb565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506127c3565b60009150506127c3565b82805461461790614e8f565b90600052602060002090601f016020900481019282614639576000855561469d565b82601f10614670578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082351617855561469d565b8280016001018555821561469d579182015b8281111561469d578235825591602001919060010190614682565b506146a99291506146c7565b5090565b5080546000825590600052602060002090810190613d2891905b5b808211156146a957600081556001016146c8565b73ffffffffffffffffffffffffffffffffffffffff81168114613d2857600080fd5b60006020828403121561471057600080fd5b8135613d56816146dc565b803567ffffffffffffffff8116811461473357600080fd5b919050565b60008060008060008060a0878903121561475157600080fd5b61475a8761471b565b95506147686020880161471b565b94506040870135935060608701359250608087013567ffffffffffffffff8082111561479357600080fd5b818901915089601f8301126147a757600080fd5b8135818111156147b657600080fd5b8a60208285010111156147c857600080fd5b6020830194508093505050509295509295509295565b600081518084526020808501945080840160005b8381101561482457815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016147f2565b509495945050505050565b6fffffffffffffffffffffffffffffffff8316815260406020820152600061485a60408301846147de565b949350505050565b6000806040838503121561487557600080fd5b61487e8361471b565b915061488c6020840161471b565b90509250929050565b600080600080608085870312156148ab57600080fd5b6148b48561471b565b93506148c26020860161471b565b93969395505050506040820135916060013590565b6000602082840312156148e957600080fd5b5035919050565b6000806040838503121561490357600080fd5b823561490e816146dc565b9150602083013561491e816146dc565b809150509250929050565b6fffffffffffffffffffffffffffffffff81168114613d2857600080fd5b60006020828403121561495957600080fd5b8135613d5681614929565b60006020828403121561497657600080fd5b613d568261471b565b6000806000806080858703121561499557600080fd5b61499e8561471b565b966020860135965060408601359560600135945092505050565b600080604083850312156149cb57600080fd5b82356149d6816146dc565b9150602083013561491e81614929565b600080604083850312156149f957600080fd5b8235614a0481614929565b946020939093013593505050565b600080600060608486031215614a2757600080fd5b614a308461471b565b9250614a3e6020850161471b565b91506040840135614a4e816146dc565b809150509250925092565b602081526000613d5660208301846147de565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b83811015614b35577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089870301855282518051808852835b81811015614ae7578281018a01518982018b01528901614acc565b81811115614af757848a838b0101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01696909601870195509386019391860191600101614a94565b509398975050505050505050565b606081526000614b5660608301866147de565b8281036020840152614b6881866147de565b90508281036040840152614b7c81856147de565b9695505050505050565b60008060008060808587031215614b9c57600080fd5b8451614ba7816146dc565b6020860151909450614bb881614929565b6040860151909350614bc981614929565b6060860151909250614bda81614929565b939692955090935050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680614c2f57614c2f614be5565b92169190910692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015614c7c57614c7c614c3b565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614cb957614cb9614c3b565b500290565b600082614ccd57614ccd614be5565b500490565b60008219821115614ce557614ce5614c3b565b500190565b60008060408385031215614cfd57600080fd5b8251614d0881614929565b602084015190925061491e81614929565b60006fffffffffffffffffffffffffffffffff808316818516808303821115614d4457614d44614c3b565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818103614d7257614d72614c3b565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ddc57614ddc614c3b565b5060010190565b600067ffffffffffffffff808a16835280891660208401525086604083015285606083015260c060808301528360c0830152838560e0840137600060e0858401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011683010190506fffffffffffffffffffffffffffffffff831660a083015298975050505050505050565b600060208284031215614e8857600080fd5b5051919050565b600181811c90821680614ea357607f821691505b602082108103614edc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006fffffffffffffffffffffffffffffffff821680614f0457614f04614c3b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600081518084526020808501945080840160005b838110156148245781516fffffffffffffffffffffffffffffffff1687529582019590820190600101614f6f565b604081526000614fb06040830185614f5b565b8281036020840152614fc28185614f5b565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220893a406362eba55f17f068b1bb867ad4acb7b8a04f007b8ef915048dea5447af64736f6c634300080d0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.