Overview
ETH Balance
0.041002953850657494 ETH
Eth Value
$142.85 (@ $3,483.85/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 5,862 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Delegate | 21474915 | 3 hrs ago | IN | 0 ETH | 0.00046369 | ||||
Complete Undeleg... | 21474419 | 5 hrs ago | IN | 0 ETH | 0.00042959 | ||||
Undelegate Token... | 21473890 | 6 hrs ago | IN | 0 ETH | 0.00078442 | ||||
Complete Undeleg... | 21473776 | 7 hrs ago | IN | 0 ETH | 0.00053894 | ||||
Delegate | 21471525 | 14 hrs ago | IN | 0 ETH | 0.00053576 | ||||
Undelegate Token... | 21470821 | 17 hrs ago | IN | 0 ETH | 0.000638 | ||||
Undelegate Token... | 21470818 | 17 hrs ago | IN | 0 ETH | 0.00059922 | ||||
Undelegate Token... | 21470809 | 17 hrs ago | IN | 0 ETH | 0.00066327 | ||||
Undelegate Token... | 21470792 | 17 hrs ago | IN | 0 ETH | 0.0007014 | ||||
Undelegate Token... | 21470789 | 17 hrs ago | IN | 0 ETH | 0.00070543 | ||||
Delegate | 21469660 | 21 hrs ago | IN | 0 ETH | 0.00064071 | ||||
Undelegate Token... | 21469630 | 21 hrs ago | IN | 0 ETH | 0.00087191 | ||||
Complete Undeleg... | 21469620 | 21 hrs ago | IN | 0 ETH | 0.0005697 | ||||
Delegate | 21465955 | 33 hrs ago | IN | 0 ETH | 0.00188813 | ||||
Undelegate Token... | 21465486 | 35 hrs ago | IN | 0 ETH | 0.00086226 | ||||
Undelegate Token... | 21462484 | 45 hrs ago | IN | 0 ETH | 0.00129405 | ||||
Complete Undeleg... | 21462475 | 45 hrs ago | IN | 0 ETH | 0.00069551 | ||||
Undelegate Token... | 21461453 | 2 days ago | IN | 0 ETH | 0.00072663 | ||||
Undelegate Token... | 21461431 | 2 days ago | IN | 0 ETH | 0.00064642 | ||||
Undelegate Token... | 21458276 | 2 days ago | IN | 0 ETH | 0.00095167 | ||||
Delegate | 21455392 | 2 days ago | IN | 0 ETH | 0.00060933 | ||||
Delegate | 21455362 | 2 days ago | IN | 0 ETH | 0.00057848 | ||||
Complete Undeleg... | 21453465 | 3 days ago | IN | 0 ETH | 0.00048947 | ||||
Undelegate Token... | 21453196 | 3 days ago | IN | 0 ETH | 0.00115163 | ||||
Undelegate Token... | 21451942 | 3 days ago | IN | 0 ETH | 0.00098208 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Staking
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.9; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {DataTypes as dt} from "./libraries/DataTypes.sol"; import "./interfaces/ISigsVerifier.sol"; import "./libraries/PbStaking.sol"; import "./Whitelist.sol"; import "./Pauser.sol"; /** * @title A Staking contract shared by all external sidechains and apps */ contract Staking is ISigsVerifier, Pauser, Whitelist { using SafeERC20 for IERC20; using ECDSA for bytes32; IERC20 public immutable CELER_TOKEN; uint256 public bondedTokens; uint256 public nextBondBlock; address[] public valAddrs; address[] public bondedValAddrs; mapping(address => dt.Validator) public validators; // key is valAddr mapping(address => address) public signerVals; // signerAddr -> valAddr mapping(uint256 => bool) public slashNonces; mapping(dt.ParamName => uint256) public params; address public govContract; address public rewardContract; uint256 public forfeiture; /* Events */ event ValidatorNotice(address indexed valAddr, string key, bytes data, address from); event ValidatorStatusUpdate(address indexed valAddr, dt.ValidatorStatus indexed status); event DelegationUpdate( address indexed valAddr, address indexed delAddr, uint256 valTokens, uint256 delShares, int256 tokenDiff ); event Undelegated(address indexed valAddr, address indexed delAddr, uint256 amount); event Slash(address indexed valAddr, uint64 nonce, uint256 slashAmt); event SlashAmtCollected(address indexed recipient, uint256 amount); /** * @notice Staking constructor * @param _celerTokenAddress address of Celer Token Contract * @param _proposalDeposit required deposit amount for a governance proposal * @param _votingPeriod voting timeout for a governance proposal * @param _unbondingPeriod the locking time for funds locked before withdrawn * @param _maxBondedValidators the maximum number of bonded validators * @param _minValidatorTokens the global minimum token amount requirement for bonded validator * @param _minSelfDelegation minimal amount of self-delegated tokens * @param _advanceNoticePeriod the wait time after the announcement and prior to the effective date of an update * @param _validatorBondInterval min interval between bondValidator * @param _maxSlashFactor maximal slashing factor (1e6 = 100%) */ constructor( address _celerTokenAddress, uint256 _proposalDeposit, uint256 _votingPeriod, uint256 _unbondingPeriod, uint256 _maxBondedValidators, uint256 _minValidatorTokens, uint256 _minSelfDelegation, uint256 _advanceNoticePeriod, uint256 _validatorBondInterval, uint256 _maxSlashFactor ) { CELER_TOKEN = IERC20(_celerTokenAddress); params[dt.ParamName.ProposalDeposit] = _proposalDeposit; params[dt.ParamName.VotingPeriod] = _votingPeriod; params[dt.ParamName.UnbondingPeriod] = _unbondingPeriod; params[dt.ParamName.MaxBondedValidators] = _maxBondedValidators; params[dt.ParamName.MinValidatorTokens] = _minValidatorTokens; params[dt.ParamName.MinSelfDelegation] = _minSelfDelegation; params[dt.ParamName.AdvanceNoticePeriod] = _advanceNoticePeriod; params[dt.ParamName.ValidatorBondInterval] = _validatorBondInterval; params[dt.ParamName.MaxSlashFactor] = _maxSlashFactor; } receive() external payable {} /********************************* * External and Public Functions * *********************************/ /** * @notice Initialize a validator candidate * @param _signer signer address * @param _minSelfDelegation minimal amount of tokens staked by the validator itself * @param _commissionRate the self-declaimed commission rate */ function initializeValidator( address _signer, uint256 _minSelfDelegation, uint64 _commissionRate ) external whenNotPaused onlyWhitelisted { address valAddr = msg.sender; dt.Validator storage validator = validators[valAddr]; require(validator.status == dt.ValidatorStatus.Null, "Validator is initialized"); require(validators[_signer].status == dt.ValidatorStatus.Null, "Signer is other validator"); require(signerVals[valAddr] == address(0), "Validator is other signer"); require(signerVals[_signer] == address(0), "Signer already used"); require(_commissionRate <= dt.COMMISSION_RATE_BASE, "Invalid commission rate"); require(_minSelfDelegation >= params[dt.ParamName.MinSelfDelegation], "Insufficient min self delegation"); validator.signer = _signer; validator.status = dt.ValidatorStatus.Unbonded; validator.minSelfDelegation = _minSelfDelegation; validator.commissionRate = _commissionRate; valAddrs.push(valAddr); signerVals[_signer] = valAddr; delegate(valAddr, _minSelfDelegation); emit ValidatorNotice(valAddr, "init", abi.encode(_signer, _minSelfDelegation, _commissionRate), address(0)); } /** * @notice Update validator signer address * @param _signer signer address */ function updateValidatorSigner(address _signer) external { address valAddr = msg.sender; dt.Validator storage validator = validators[valAddr]; require(validator.status != dt.ValidatorStatus.Null, "Validator not initialized"); require(signerVals[_signer] == address(0), "Signer already used"); if (_signer != valAddr) { require(validators[_signer].status == dt.ValidatorStatus.Null, "Signer is other validator"); } delete signerVals[validator.signer]; validator.signer = _signer; signerVals[_signer] = valAddr; emit ValidatorNotice(valAddr, "signer", abi.encode(_signer), address(0)); } /** * @notice Candidate claims to become a bonded validator * @dev caller can be either validator owner or signer */ function bondValidator() external { address valAddr = msg.sender; if (signerVals[msg.sender] != address(0)) { valAddr = signerVals[msg.sender]; } dt.Validator storage validator = validators[valAddr]; require( validator.status == dt.ValidatorStatus.Unbonded || validator.status == dt.ValidatorStatus.Unbonding, "Invalid validator status" ); require(block.number >= validator.bondBlock, "Bond block not reached"); require(block.number >= nextBondBlock, "Too frequent validator bond"); nextBondBlock = block.number + params[dt.ParamName.ValidatorBondInterval]; require(hasMinRequiredTokens(valAddr, true), "Not have min tokens"); uint256 maxBondedValidators = params[dt.ParamName.MaxBondedValidators]; // if the number of validators has not reached the max_validator_num, // add validator directly if (bondedValAddrs.length < maxBondedValidators) { _bondValidator(valAddr); _decentralizationCheck(validator.tokens); return; } // if the number of validators has already reached the max_validator_num, // add validator only if its tokens is more than the current least bonded validator tokens uint256 minTokens = dt.MAX_INT; uint256 minTokensIndex; for (uint256 i = 0; i < maxBondedValidators; i++) { if (validators[bondedValAddrs[i]].tokens < minTokens) { minTokensIndex = i; minTokens = validators[bondedValAddrs[i]].tokens; if (minTokens == 0) { break; } } } require(validator.tokens > minTokens, "Insufficient tokens"); _replaceBondedValidator(valAddr, minTokensIndex); _decentralizationCheck(validator.tokens); } /** * @notice Confirm validator status from Unbonding to Unbonded * @param _valAddr the address of the validator */ function confirmUnbondedValidator(address _valAddr) external { dt.Validator storage validator = validators[_valAddr]; require(validator.status == dt.ValidatorStatus.Unbonding, "Validator not unbonding"); require(block.number >= validator.unbondBlock, "Unbond block not reached"); validator.status = dt.ValidatorStatus.Unbonded; delete validator.unbondBlock; emit ValidatorStatusUpdate(_valAddr, dt.ValidatorStatus.Unbonded); } /** * @notice Delegate CELR tokens to a validator * @dev Minimal amount per delegate operation is 1 CELR * @param _valAddr validator to delegate * @param _tokens the amount of delegated CELR tokens */ function delegate(address _valAddr, uint256 _tokens) public whenNotPaused { address delAddr = msg.sender; require(_tokens >= dt.CELR_DECIMAL, "Minimal amount is 1 CELR"); dt.Validator storage validator = validators[_valAddr]; require(validator.status != dt.ValidatorStatus.Null, "Validator is not initialized"); uint256 shares = _tokenToShare(_tokens, validator.tokens, validator.shares); dt.Delegator storage delegator = validator.delegators[delAddr]; delegator.shares += shares; validator.shares += shares; validator.tokens += _tokens; if (validator.status == dt.ValidatorStatus.Bonded) { bondedTokens += _tokens; _decentralizationCheck(validator.tokens); } CELER_TOKEN.safeTransferFrom(delAddr, address(this), _tokens); emit DelegationUpdate(_valAddr, delAddr, validator.tokens, delegator.shares, int256(_tokens)); } /** * @notice Undelegate shares from a validator * @dev Tokens are delegated by the msgSender to the validator * @param _valAddr the address of the validator * @param _shares undelegate shares */ function undelegateShares(address _valAddr, uint256 _shares) external { require(_shares >= dt.CELR_DECIMAL, "Minimal amount is 1 share"); dt.Validator storage validator = validators[_valAddr]; require(validator.status != dt.ValidatorStatus.Null, "Validator is not initialized"); uint256 tokens = _shareToToken(_shares, validator.tokens, validator.shares); _undelegate(validator, _valAddr, tokens, _shares); } /** * @notice Undelegate shares from a validator * @dev Tokens are delegated by the msgSender to the validator * @param _valAddr the address of the validator * @param _tokens undelegate tokens */ function undelegateTokens(address _valAddr, uint256 _tokens) external { require(_tokens >= dt.CELR_DECIMAL, "Minimal amount is 1 CELR"); dt.Validator storage validator = validators[_valAddr]; require(validator.status != dt.ValidatorStatus.Null, "Validator is not initialized"); uint256 shares = _tokenToShare(_tokens, validator.tokens, validator.shares); _undelegate(validator, _valAddr, _tokens, shares); } /** * @notice Complete pending undelegations from a validator * @param _valAddr the address of the validator */ function completeUndelegate(address _valAddr) external { address delAddr = msg.sender; dt.Validator storage validator = validators[_valAddr]; require(validator.status != dt.ValidatorStatus.Null, "Validator is not initialized"); dt.Delegator storage delegator = validator.delegators[delAddr]; uint256 unbondingPeriod = params[dt.ParamName.UnbondingPeriod]; bool isUnbonded = validator.status == dt.ValidatorStatus.Unbonded; // for all pending undelegations uint32 i; uint256 undelegationShares; for (i = delegator.undelegations.head; i < delegator.undelegations.tail; i++) { if (isUnbonded || delegator.undelegations.queue[i].creationBlock + unbondingPeriod <= block.number) { // complete undelegation when the validator becomes unbonded or // the unbondingPeriod for the pending undelegation is up. undelegationShares += delegator.undelegations.queue[i].shares; delete delegator.undelegations.queue[i]; continue; } break; } delegator.undelegations.head = i; require(undelegationShares > 0, "No undelegation ready to be completed"); uint256 tokens = _shareToToken(undelegationShares, validator.undelegationTokens, validator.undelegationShares); validator.undelegationShares -= undelegationShares; validator.undelegationTokens -= tokens; CELER_TOKEN.safeTransfer(delAddr, tokens); emit Undelegated(_valAddr, delAddr, tokens); } /** * @notice Update commission rate * @param _newRate new commission rate */ function updateCommissionRate(uint64 _newRate) external { address valAddr = msg.sender; dt.Validator storage validator = validators[valAddr]; require(validator.status != dt.ValidatorStatus.Null, "Validator is not initialized"); require(_newRate <= dt.COMMISSION_RATE_BASE, "Invalid new rate"); validator.commissionRate = _newRate; emit ValidatorNotice(valAddr, "commission", abi.encode(_newRate), address(0)); } /** * @notice Update minimal self delegation value * @param _minSelfDelegation minimal amount of tokens staked by the validator itself */ function updateMinSelfDelegation(uint256 _minSelfDelegation) external { address valAddr = msg.sender; dt.Validator storage validator = validators[valAddr]; require(validator.status != dt.ValidatorStatus.Null, "Validator is not initialized"); require(_minSelfDelegation >= params[dt.ParamName.MinSelfDelegation], "Insufficient min self delegation"); if (_minSelfDelegation < validator.minSelfDelegation) { require(validator.status != dt.ValidatorStatus.Bonded, "Validator is bonded"); validator.bondBlock = uint64(block.number + params[dt.ParamName.AdvanceNoticePeriod]); } validator.minSelfDelegation = _minSelfDelegation; emit ValidatorNotice(valAddr, "min-self-delegation", abi.encode(_minSelfDelegation), address(0)); } /** * @notice Slash a validator and its delegators * @param _slashRequest slash request bytes coded in protobuf * @param _sigs list of validator signatures */ function slash(bytes calldata _slashRequest, bytes[] calldata _sigs) external whenNotPaused { bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "Slash")); verifySignatures(abi.encodePacked(domain, _slashRequest), _sigs); PbStaking.Slash memory request = PbStaking.decSlash(_slashRequest); require(block.timestamp < request.expireTime, "Slash expired"); require(request.slashFactor <= dt.SLASH_FACTOR_DECIMAL, "Invalid slash factor"); require(request.slashFactor <= params[dt.ParamName.MaxSlashFactor], "Exceed max slash factor"); require(!slashNonces[request.nonce], "Used slash nonce"); slashNonces[request.nonce] = true; address valAddr = request.validator; dt.Validator storage validator = validators[valAddr]; require( validator.status == dt.ValidatorStatus.Bonded || validator.status == dt.ValidatorStatus.Unbonding, "Invalid validator status" ); // slash delegated tokens uint256 slashAmt = (validator.tokens * request.slashFactor) / dt.SLASH_FACTOR_DECIMAL; validator.tokens -= slashAmt; if (validator.status == dt.ValidatorStatus.Bonded) { bondedTokens -= slashAmt; if (request.jailPeriod > 0 || !hasMinRequiredTokens(valAddr, true)) { _unbondValidator(valAddr); } } if (validator.status == dt.ValidatorStatus.Unbonding && request.jailPeriod > 0) { validator.bondBlock = uint64(block.number + request.jailPeriod); } emit DelegationUpdate(valAddr, address(0), validator.tokens, 0, -int256(slashAmt)); // slash pending undelegations uint256 slashUndelegation = (validator.undelegationTokens * request.slashFactor) / dt.SLASH_FACTOR_DECIMAL; validator.undelegationTokens -= slashUndelegation; slashAmt += slashUndelegation; uint256 collectAmt; for (uint256 i = 0; i < request.collectors.length; i++) { PbStaking.AcctAmtPair memory collector = request.collectors[i]; if (collectAmt + collector.amount > slashAmt) { collector.amount = slashAmt - collectAmt; } if (collector.amount > 0) { collectAmt += collector.amount; if (collector.account == address(0)) { CELER_TOKEN.safeTransfer(msg.sender, collector.amount); emit SlashAmtCollected(msg.sender, collector.amount); } else { CELER_TOKEN.safeTransfer(collector.account, collector.amount); emit SlashAmtCollected(collector.account, collector.amount); } } } forfeiture += slashAmt - collectAmt; emit Slash(valAddr, request.nonce, slashAmt); } function collectForfeiture() external { require(forfeiture > 0, "Nothing to collect"); CELER_TOKEN.safeTransfer(rewardContract, forfeiture); forfeiture = 0; } /** * @notice Validator notice event, could be triggered by anyone */ function validatorNotice( address _valAddr, string calldata _key, bytes calldata _data ) external { dt.Validator storage validator = validators[_valAddr]; require(validator.status != dt.ValidatorStatus.Null, "Validator is not initialized"); emit ValidatorNotice(_valAddr, _key, _data, msg.sender); } function setParamValue(dt.ParamName _name, uint256 _value) external { require(msg.sender == govContract, "Caller is not gov contract"); if (_name == dt.ParamName.MaxBondedValidators) { require(bondedValAddrs.length <= _value, "invalid value"); } params[_name] = _value; } function setGovContract(address _addr) external onlyOwner { govContract = _addr; } function setRewardContract(address _addr) external onlyOwner { rewardContract = _addr; } /** * @notice Set max slash factor */ function setMaxSlashFactor(uint256 _maxSlashFactor) external onlyOwner { params[dt.ParamName.MaxSlashFactor] = _maxSlashFactor; } /** * @notice Owner drains tokens when the contract is paused * @dev emergency use only * @param _amount drained token amount */ function drainToken(uint256 _amount) external whenPaused onlyOwner { CELER_TOKEN.safeTransfer(msg.sender, _amount); } /************************** * Public View Functions * **************************/ /** * @notice Validate if a message is signed by quorum tokens * @param _msg signed message * @param _sigs list of validator signatures */ function verifySignatures(bytes memory _msg, bytes[] memory _sigs) public view returns (bool) { bytes32 hash = keccak256(_msg).toEthSignedMessageHash(); uint256 signedTokens; address prev = address(0); uint256 quorum = getQuorumTokens(); for (uint256 i = 0; i < _sigs.length; i++) { address signer = hash.recover(_sigs[i]); require(signer > prev, "Signers not in ascending order"); prev = signer; dt.Validator storage validator = validators[signerVals[signer]]; if (validator.status != dt.ValidatorStatus.Bonded) { continue; } signedTokens += validator.tokens; if (signedTokens >= quorum) { return true; } } revert("Quorum not reached"); } /** * @notice Verifies that a message is signed by a quorum among the validators. * @param _msg signed message * @param _sigs the list of signatures */ function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata, uint256[] calldata ) public view override { require(verifySignatures(_msg, _sigs), "Failed to verify sigs"); } /** * @notice Get quorum amount of tokens * @return the quorum amount */ function getQuorumTokens() public view returns (uint256) { return (bondedTokens * 2) / 3 + 1; } /** * @notice Get validator info * @param _valAddr the address of the validator * @return Validator token amount */ function getValidatorTokens(address _valAddr) public view returns (uint256) { return validators[_valAddr].tokens; } /** * @notice Get validator info * @param _valAddr the address of the validator * @return Validator status */ function getValidatorStatus(address _valAddr) public view returns (dt.ValidatorStatus) { return validators[_valAddr].status; } /** * @notice Check the given address is a validator or not * @param _addr the address to check * @return the given address is a validator or not */ function isBondedValidator(address _addr) public view returns (bool) { return validators[_addr].status == dt.ValidatorStatus.Bonded; } /** * @notice Get the number of validators * @return the number of validators */ function getValidatorNum() public view returns (uint256) { return valAddrs.length; } /** * @notice Get the number of bonded validators * @return the number of bonded validators */ function getBondedValidatorNum() public view returns (uint256) { return bondedValAddrs.length; } /** * @return addresses and token amounts of bonded validators */ function getBondedValidatorsTokens() public view returns (dt.ValidatorTokens[] memory) { dt.ValidatorTokens[] memory infos = new dt.ValidatorTokens[](bondedValAddrs.length); for (uint256 i = 0; i < bondedValAddrs.length; i++) { address valAddr = bondedValAddrs[i]; infos[i] = dt.ValidatorTokens(valAddr, validators[valAddr].tokens); } return infos; } /** * @notice Check if min token requirements are met * @param _valAddr the address of the validator * @param _checkSelfDelegation check self delegation */ function hasMinRequiredTokens(address _valAddr, bool _checkSelfDelegation) public view returns (bool) { dt.Validator storage v = validators[_valAddr]; uint256 valTokens = v.tokens; if (valTokens < params[dt.ParamName.MinValidatorTokens]) { return false; } if (_checkSelfDelegation) { uint256 selfDelegation = _shareToToken(v.delegators[_valAddr].shares, valTokens, v.shares); if (selfDelegation < v.minSelfDelegation) { return false; } } return true; } /** * @notice Get the delegator info of a specific validator * @param _valAddr the address of the validator * @param _delAddr the address of the delegator * @return DelegatorInfo from the given validator */ function getDelegatorInfo(address _valAddr, address _delAddr) public view returns (dt.DelegatorInfo memory) { dt.Validator storage validator = validators[_valAddr]; dt.Delegator storage d = validator.delegators[_delAddr]; uint256 tokens = _shareToToken(d.shares, validator.tokens, validator.shares); uint256 undelegationShares; uint256 withdrawableUndelegationShares; uint256 unbondingPeriod = params[dt.ParamName.UnbondingPeriod]; bool isUnbonded = validator.status == dt.ValidatorStatus.Unbonded; uint256 len = d.undelegations.tail - d.undelegations.head; dt.Undelegation[] memory undelegations = new dt.Undelegation[](len); for (uint256 i = 0; i < len; i++) { undelegations[i] = d.undelegations.queue[i + d.undelegations.head]; undelegationShares += undelegations[i].shares; if (isUnbonded || undelegations[i].creationBlock + unbondingPeriod <= block.number) { withdrawableUndelegationShares += undelegations[i].shares; } } uint256 undelegationTokens = _shareToToken( undelegationShares, validator.undelegationTokens, validator.undelegationShares ); uint256 withdrawableUndelegationTokens = _shareToToken( withdrawableUndelegationShares, validator.undelegationTokens, validator.undelegationShares ); return dt.DelegatorInfo( _valAddr, tokens, d.shares, undelegations, undelegationTokens, withdrawableUndelegationTokens ); } /** * @notice Get the value of a specific uint parameter * @param _name the key of this parameter * @return the value of this parameter */ function getParamValue(dt.ParamName _name) public view returns (uint256) { return params[_name]; } /********************* * Private Functions * *********************/ function _undelegate( dt.Validator storage validator, address _valAddr, uint256 _tokens, uint256 _shares ) private { address delAddr = msg.sender; dt.Delegator storage delegator = validator.delegators[delAddr]; delegator.shares -= _shares; validator.shares -= _shares; validator.tokens -= _tokens; if (validator.tokens != validator.shares && delegator.shares <= 2) { // Remove residual share caused by rounding error when total shares and tokens are not equal validator.shares -= delegator.shares; delegator.shares = 0; } require(delegator.shares == 0 || delegator.shares >= dt.CELR_DECIMAL, "not enough remaining shares"); if (validator.status == dt.ValidatorStatus.Unbonded) { CELER_TOKEN.safeTransfer(delAddr, _tokens); emit Undelegated(_valAddr, delAddr, _tokens); return; } else if (validator.status == dt.ValidatorStatus.Bonded) { bondedTokens -= _tokens; if (!hasMinRequiredTokens(_valAddr, delAddr == _valAddr)) { _unbondValidator(_valAddr); } } require( delegator.undelegations.tail - delegator.undelegations.head < dt.MAX_UNDELEGATION_ENTRIES, "Exceed max undelegation entries" ); uint256 undelegationShares = _tokenToShare(_tokens, validator.undelegationTokens, validator.undelegationShares); validator.undelegationShares += undelegationShares; validator.undelegationTokens += _tokens; dt.Undelegation storage undelegation = delegator.undelegations.queue[delegator.undelegations.tail]; undelegation.shares = undelegationShares; undelegation.creationBlock = block.number; delegator.undelegations.tail++; emit DelegationUpdate(_valAddr, delAddr, validator.tokens, delegator.shares, -int256(_tokens)); } /** * @notice Set validator to bonded * @param _valAddr the address of the validator */ function _setBondedValidator(address _valAddr) private { dt.Validator storage validator = validators[_valAddr]; validator.status = dt.ValidatorStatus.Bonded; delete validator.unbondBlock; bondedTokens += validator.tokens; emit ValidatorStatusUpdate(_valAddr, dt.ValidatorStatus.Bonded); } /** * @notice Set validator to unbonding * @param _valAddr the address of the validator */ function _setUnbondingValidator(address _valAddr) private { dt.Validator storage validator = validators[_valAddr]; validator.status = dt.ValidatorStatus.Unbonding; validator.unbondBlock = uint64(block.number + params[dt.ParamName.UnbondingPeriod]); bondedTokens -= validator.tokens; emit ValidatorStatusUpdate(_valAddr, dt.ValidatorStatus.Unbonding); } /** * @notice Bond a validator * @param _valAddr the address of the validator */ function _bondValidator(address _valAddr) private { bondedValAddrs.push(_valAddr); _setBondedValidator(_valAddr); } /** * @notice Replace a bonded validator * @param _valAddr the address of the new validator * @param _index the index of the validator to be replaced */ function _replaceBondedValidator(address _valAddr, uint256 _index) private { _setUnbondingValidator(bondedValAddrs[_index]); bondedValAddrs[_index] = _valAddr; _setBondedValidator(_valAddr); } /** * @notice Unbond a validator * @param _valAddr validator to be removed */ function _unbondValidator(address _valAddr) private { uint256 lastIndex = bondedValAddrs.length - 1; for (uint256 i = 0; i < bondedValAddrs.length; i++) { if (bondedValAddrs[i] == _valAddr) { if (i < lastIndex) { bondedValAddrs[i] = bondedValAddrs[lastIndex]; } bondedValAddrs.pop(); _setUnbondingValidator(_valAddr); return; } } revert("Not bonded validator"); } /** * @notice Check if one validator as too much power * @param _valTokens token amounts of the validator */ function _decentralizationCheck(uint256 _valTokens) private view { uint256 bondedValNum = bondedValAddrs.length; if (bondedValNum == 2 || bondedValNum == 3) { require(_valTokens < getQuorumTokens(), "Single validator should not have quorum tokens"); } else if (bondedValNum > 3) { require(_valTokens < bondedTokens / 3, "Single validator should not have 1/3 tokens"); } } /** * @notice Convert token to share */ function _tokenToShare( uint256 tokens, uint256 totalTokens, uint256 totalShares ) private pure returns (uint256) { if (totalTokens == 0) { return tokens; } return (tokens * totalShares) / totalTokens; } /** * @notice Convert share to token */ function _shareToToken( uint256 shares, uint256 totalTokens, uint256 totalShares ) private pure returns (uint256) { if (totalShares == 0) { return shares; } return (shares * totalTokens) / totalShares; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.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 Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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 { _setOwner(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"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) private 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /* * @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 Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return recover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return recover(hash, r, vs); } else { revert("ECDSA: invalid signature length"); } } /** * @dev Overload of {ECDSA-recover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { bytes32 s; uint8 v; assembly { s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) v := add(shr(255, vs), 27) } return recover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. require( uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value" ); require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value"); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "ECDSA: invalid signature"); return signer; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.9; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; abstract contract Pauser is Ownable, Pausable { mapping(address => bool) public pausers; event PauserAdded(address account); event PauserRemoved(address account); constructor() { _addPauser(msg.sender); } modifier onlyPauser() { require(isPauser(msg.sender), "Caller is not pauser"); _; } function pause() public onlyPauser { _pause(); } function unpause() public onlyPauser { _unpause(); } function isPauser(address account) public view returns (bool) { return pausers[account]; } function addPauser(address account) public onlyOwner { _addPauser(account); } function removePauser(address account) public onlyOwner { _removePauser(account); } function renouncePauser() public { _removePauser(msg.sender); } function _addPauser(address account) private { require(!isPauser(account), "Account is already pauser"); pausers[account] = true; emit PauserAdded(account); } function _removePauser(address account) private { require(isPauser(account), "Account is not pauser"); pausers[account] = false; emit PauserRemoved(account); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.9; import "@openzeppelin/contracts/access/Ownable.sol"; abstract contract Whitelist is Ownable { mapping(address => bool) public whitelist; bool public whitelistEnabled; event WhitelistedAdded(address account); event WhitelistedRemoved(address account); modifier onlyWhitelisted() { if (whitelistEnabled) { require(isWhitelisted(msg.sender), "Caller is not whitelisted"); } _; } /** * @notice Set whitelistEnabled */ function setWhitelistEnabled(bool _whitelistEnabled) external onlyOwner { whitelistEnabled = _whitelistEnabled; } /** * @notice Add an account to whitelist */ function addWhitelisted(address account) external onlyOwner { require(!isWhitelisted(account), "Already whitelisted"); whitelist[account] = true; emit WhitelistedAdded(account); } /** * @notice Remove an account from whitelist */ function removeWhitelisted(address account) external onlyOwner { require(isWhitelisted(account), "Not whitelisted"); whitelist[account] = false; emit WhitelistedRemoved(account); } /** * @return is account whitelisted */ function isWhitelisted(address account) public view returns (bool) { return whitelist[account]; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.9; interface ISigsVerifier { /** * @notice Verifies that a message is signed by a quorum among the signers. * @param _msg signed message * @param _sigs list of signatures sorted by signer addresses * @param _signers sorted list of current signers * @param _powers powers of current signers */ function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external view; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.9; library DataTypes { uint256 constant CELR_DECIMAL = 1e18; uint256 constant MAX_INT = 2**256 - 1; uint256 constant COMMISSION_RATE_BASE = 10000; // 1 commissionRate means 0.01% uint256 constant MAX_UNDELEGATION_ENTRIES = 10; uint256 constant SLASH_FACTOR_DECIMAL = 1e6; enum ValidatorStatus { Null, Unbonded, Unbonding, Bonded } enum ParamName { ProposalDeposit, VotingPeriod, UnbondingPeriod, MaxBondedValidators, MinValidatorTokens, MinSelfDelegation, AdvanceNoticePeriod, ValidatorBondInterval, MaxSlashFactor } struct Undelegation { uint256 shares; uint256 creationBlock; } struct Undelegations { mapping(uint256 => Undelegation) queue; uint32 head; uint32 tail; } struct Delegator { uint256 shares; Undelegations undelegations; } struct Validator { ValidatorStatus status; address signer; uint256 tokens; // sum of all tokens delegated to this validator uint256 shares; // sum of all delegation shares uint256 undelegationTokens; // tokens being undelegated uint256 undelegationShares; // shares of tokens being undelegated mapping(address => Delegator) delegators; uint256 minSelfDelegation; uint64 bondBlock; // cannot become bonded before this block uint64 unbondBlock; // cannot become unbonded before this block uint64 commissionRate; // equal to real commission rate * COMMISSION_RATE_BASE } // used for external view output struct ValidatorTokens { address valAddr; uint256 tokens; } // used for external view output struct ValidatorInfo { address valAddr; ValidatorStatus status; address signer; uint256 tokens; uint256 shares; uint256 minSelfDelegation; uint64 commissionRate; } // used for external view output struct DelegatorInfo { address valAddr; uint256 tokens; uint256 shares; Undelegation[] undelegations; uint256 undelegationTokens; uint256 withdrawableUndelegationTokens; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.9; // runtime proto sol library library Pb { enum WireType { Varint, Fixed64, LengthDelim, StartGroup, EndGroup, Fixed32 } struct Buffer { uint256 idx; // the start index of next read. when idx=b.length, we're done bytes b; // hold serialized proto msg, readonly } // create a new in-memory Buffer object from raw msg bytes function fromBytes(bytes memory raw) internal pure returns (Buffer memory buf) { buf.b = raw; buf.idx = 0; } // whether there are unread bytes function hasMore(Buffer memory buf) internal pure returns (bool) { return buf.idx < buf.b.length; } // decode current field number and wiretype function decKey(Buffer memory buf) internal pure returns (uint256 tag, WireType wiretype) { uint256 v = decVarint(buf); tag = v / 8; wiretype = WireType(v & 7); } // count tag occurrences, return an array due to no memory map support // have to create array for (maxtag+1) size. cnts[tag] = occurrences // should keep buf.idx unchanged because this is only a count function function cntTags(Buffer memory buf, uint256 maxtag) internal pure returns (uint256[] memory cnts) { uint256 originalIdx = buf.idx; cnts = new uint256[](maxtag + 1); // protobuf's tags are from 1 rather than 0 uint256 tag; WireType wire; while (hasMore(buf)) { (tag, wire) = decKey(buf); cnts[tag] += 1; skipValue(buf, wire); } buf.idx = originalIdx; } // read varint from current buf idx, move buf.idx to next read, return the int value function decVarint(Buffer memory buf) internal pure returns (uint256 v) { bytes10 tmp; // proto int is at most 10 bytes (7 bits can be used per byte) bytes memory bb = buf.b; // get buf.b mem addr to use in assembly v = buf.idx; // use v to save one additional uint variable assembly { tmp := mload(add(add(bb, 32), v)) // load 10 bytes from buf.b[buf.idx] to tmp } uint256 b; // store current byte content v = 0; // reset to 0 for return value for (uint256 i = 0; i < 10; i++) { assembly { b := byte(i, tmp) // don't use tmp[i] because it does bound check and costs extra } v |= (b & 0x7F) << (i * 7); if (b & 0x80 == 0) { buf.idx += i + 1; return v; } } revert(); // i=10, invalid varint stream } // read length delimited field and return bytes function decBytes(Buffer memory buf) internal pure returns (bytes memory b) { uint256 len = decVarint(buf); uint256 end = buf.idx + len; require(end <= buf.b.length); // avoid overflow b = new bytes(len); bytes memory bufB = buf.b; // get buf.b mem addr to use in assembly uint256 bStart; uint256 bufBStart = buf.idx; assembly { bStart := add(b, 32) bufBStart := add(add(bufB, 32), bufBStart) } for (uint256 i = 0; i < len; i += 32) { assembly { mstore(add(bStart, i), mload(add(bufBStart, i))) } } buf.idx = end; } // return packed ints function decPacked(Buffer memory buf) internal pure returns (uint256[] memory t) { uint256 len = decVarint(buf); uint256 end = buf.idx + len; require(end <= buf.b.length); // avoid overflow // array in memory must be init w/ known length // so we have to create a tmp array w/ max possible len first uint256[] memory tmp = new uint256[](len); uint256 i = 0; // count how many ints are there while (buf.idx < end) { tmp[i] = decVarint(buf); i++; } t = new uint256[](i); // init t with correct length for (uint256 j = 0; j < i; j++) { t[j] = tmp[j]; } return t; } // move idx pass current value field, to beginning of next tag or msg end function skipValue(Buffer memory buf, WireType wire) internal pure { if (wire == WireType.Varint) { decVarint(buf); } else if (wire == WireType.LengthDelim) { uint256 len = decVarint(buf); buf.idx += len; // skip len bytes value data require(buf.idx <= buf.b.length); // avoid overflow } else { revert(); } // unsupported wiretype } // type conversion help utils function _bool(uint256 x) internal pure returns (bool v) { return x != 0; } function _uint256(bytes memory b) internal pure returns (uint256 v) { require(b.length <= 32); // b's length must be smaller than or equal to 32 assembly { v := mload(add(b, 32)) } // load all 32bytes to v v = v >> (8 * (32 - b.length)); // only first b.length is valid } function _address(bytes memory b) internal pure returns (address v) { v = _addressPayable(b); } function _addressPayable(bytes memory b) internal pure returns (address payable v) { require(b.length == 20); //load 32bytes then shift right 12 bytes assembly { v := div(mload(add(b, 32)), 0x1000000000000000000000000) } } function _bytes32(bytes memory b) internal pure returns (bytes32 v) { require(b.length == 32); assembly { v := mload(add(b, 32)) } } // uint[] to uint8[] function uint8s(uint256[] memory arr) internal pure returns (uint8[] memory t) { t = new uint8[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint8(arr[i]); } } function uint32s(uint256[] memory arr) internal pure returns (uint32[] memory t) { t = new uint32[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint32(arr[i]); } } function uint64s(uint256[] memory arr) internal pure returns (uint64[] memory t) { t = new uint64[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint64(arr[i]); } } function bools(uint256[] memory arr) internal pure returns (bool[] memory t) { t = new bool[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = arr[i] != 0; } } }
// SPDX-License-Identifier: GPL-3.0-only // Code generated by protoc-gen-sol. DO NOT EDIT. // source: contracts/libraries/proto/staking.proto pragma solidity 0.8.9; import "./Pb.sol"; library PbStaking { using Pb for Pb.Buffer; // so we can call Pb funcs on Buffer obj struct StakingReward { address recipient; // tag: 1 uint256 cumulativeRewardAmount; // tag: 2 } // end struct StakingReward function decStakingReward(bytes memory raw) internal pure returns (StakingReward memory m) { Pb.Buffer memory buf = Pb.fromBytes(raw); uint256 tag; Pb.WireType wire; while (buf.hasMore()) { (tag, wire) = buf.decKey(); if (false) {} // solidity has no switch/case else if (tag == 1) { m.recipient = Pb._address(buf.decBytes()); } else if (tag == 2) { m.cumulativeRewardAmount = Pb._uint256(buf.decBytes()); } else { buf.skipValue(wire); } // skip value of unknown tag } } // end decoder StakingReward struct Slash { address validator; // tag: 1 uint64 nonce; // tag: 2 uint64 slashFactor; // tag: 3 uint64 expireTime; // tag: 4 uint64 jailPeriod; // tag: 5 AcctAmtPair[] collectors; // tag: 6 } // end struct Slash function decSlash(bytes memory raw) internal pure returns (Slash memory m) { Pb.Buffer memory buf = Pb.fromBytes(raw); uint256[] memory cnts = buf.cntTags(6); m.collectors = new AcctAmtPair[](cnts[6]); cnts[6] = 0; // reset counter for later use uint256 tag; Pb.WireType wire; while (buf.hasMore()) { (tag, wire) = buf.decKey(); if (false) {} // solidity has no switch/case else if (tag == 1) { m.validator = Pb._address(buf.decBytes()); } else if (tag == 2) { m.nonce = uint64(buf.decVarint()); } else if (tag == 3) { m.slashFactor = uint64(buf.decVarint()); } else if (tag == 4) { m.expireTime = uint64(buf.decVarint()); } else if (tag == 5) { m.jailPeriod = uint64(buf.decVarint()); } else if (tag == 6) { m.collectors[cnts[6]] = decAcctAmtPair(buf.decBytes()); cnts[6]++; } else { buf.skipValue(wire); } // skip value of unknown tag } } // end decoder Slash struct AcctAmtPair { address account; // tag: 1 uint256 amount; // tag: 2 } // end struct AcctAmtPair function decAcctAmtPair(bytes memory raw) internal pure returns (AcctAmtPair memory m) { Pb.Buffer memory buf = Pb.fromBytes(raw); uint256 tag; Pb.WireType wire; while (buf.hasMore()) { (tag, wire) = buf.decKey(); if (false) {} // solidity has no switch/case else if (tag == 1) { m.account = Pb._address(buf.decBytes()); } else if (tag == 2) { m.amount = Pb._uint256(buf.decBytes()); } else { buf.skipValue(wire); } // skip value of unknown tag } } // end decoder AcctAmtPair }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 800 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_celerTokenAddress","type":"address"},{"internalType":"uint256","name":"_proposalDeposit","type":"uint256"},{"internalType":"uint256","name":"_votingPeriod","type":"uint256"},{"internalType":"uint256","name":"_unbondingPeriod","type":"uint256"},{"internalType":"uint256","name":"_maxBondedValidators","type":"uint256"},{"internalType":"uint256","name":"_minValidatorTokens","type":"uint256"},{"internalType":"uint256","name":"_minSelfDelegation","type":"uint256"},{"internalType":"uint256","name":"_advanceNoticePeriod","type":"uint256"},{"internalType":"uint256","name":"_validatorBondInterval","type":"uint256"},{"internalType":"uint256","name":"_maxSlashFactor","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"valAddr","type":"address"},{"indexed":true,"internalType":"address","name":"delAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"valTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"delShares","type":"uint256"},{"indexed":false,"internalType":"int256","name":"tokenDiff","type":"int256"}],"name":"DelegationUpdate","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"valAddr","type":"address"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"slashAmt","type":"uint256"}],"name":"Slash","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SlashAmtCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"valAddr","type":"address"},{"indexed":true,"internalType":"address","name":"delAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Undelegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"valAddr","type":"address"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"address","name":"from","type":"address"}],"name":"ValidatorNotice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"valAddr","type":"address"},{"indexed":true,"internalType":"enum DataTypes.ValidatorStatus","name":"status","type":"uint8"}],"name":"ValidatorStatusUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"WhitelistedAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"WhitelistedRemoved","type":"event"},{"inputs":[],"name":"CELER_TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bondValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bondedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bondedValAddrs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectForfeiture","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"}],"name":"completeUndelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"}],"name":"confirmUnbondedValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"drainToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"forfeiture","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBondedValidatorNum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBondedValidatorsTokens","outputs":[{"components":[{"internalType":"address","name":"valAddr","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"}],"internalType":"struct DataTypes.ValidatorTokens[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"},{"internalType":"address","name":"_delAddr","type":"address"}],"name":"getDelegatorInfo","outputs":[{"components":[{"internalType":"address","name":"valAddr","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"},{"components":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"creationBlock","type":"uint256"}],"internalType":"struct DataTypes.Undelegation[]","name":"undelegations","type":"tuple[]"},{"internalType":"uint256","name":"undelegationTokens","type":"uint256"},{"internalType":"uint256","name":"withdrawableUndelegationTokens","type":"uint256"}],"internalType":"struct DataTypes.DelegatorInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum DataTypes.ParamName","name":"_name","type":"uint8"}],"name":"getParamValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuorumTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidatorNum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"}],"name":"getValidatorStatus","outputs":[{"internalType":"enum DataTypes.ValidatorStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"}],"name":"getValidatorTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"govContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"},{"internalType":"bool","name":"_checkSelfDelegation","type":"bool"}],"name":"hasMinRequiredTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"},{"internalType":"uint256","name":"_minSelfDelegation","type":"uint256"},{"internalType":"uint64","name":"_commissionRate","type":"uint64"}],"name":"initializeValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"isBondedValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextBondBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum DataTypes.ParamName","name":"","type":"uint8"}],"name":"params","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pausers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renouncePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setGovContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxSlashFactor","type":"uint256"}],"name":"setMaxSlashFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum DataTypes.ParamName","name":"_name","type":"uint8"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setParamValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setRewardContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_whitelistEnabled","type":"bool"}],"name":"setWhitelistEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signerVals","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_slashRequest","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"}],"name":"slash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slashNonces","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"},{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"undelegateShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"undelegateTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_newRate","type":"uint64"}],"name":"updateCommissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minSelfDelegation","type":"uint256"}],"name":"updateMinSelfDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"updateValidatorSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"valAddrs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_valAddr","type":"address"},{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"validatorNotice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validators","outputs":[{"internalType":"enum DataTypes.ValidatorStatus","name":"status","type":"uint8"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"undelegationTokens","type":"uint256"},{"internalType":"uint256","name":"undelegationShares","type":"uint256"},{"internalType":"uint256","name":"minSelfDelegation","type":"uint256"},{"internalType":"uint64","name":"bondBlock","type":"uint64"},{"internalType":"uint64","name":"unbondBlock","type":"uint64"},{"internalType":"uint64","name":"commissionRate","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_msg","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"}],"name":"verifySignatures","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_msg","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"name":"verifySigs","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620061ca380380620061ca8339810160408190526200003491620002cd565b6200003f33620001b4565b6000805460ff60a01b19169055620000573362000204565b6001600160a01b0399909916608052600b6020527fdf7de25b7f1fd6d0b5205f0e18f1f35bd7b8d84cce336588d184533ce43a6f76979097557f72c6bfb7988af3a1efa6568f02a999bc52252641c659d85961ca3d372b57d5cf959095557fa50eece07c7db1631545c0069bd8f5f54d5935e215d59097edf258a44ba91634939093557f64c15cc42be7899b001f818cf4433057002112c418d1d3a67cd5cb453051d33e919091557f12d0c11577e2f0950f57c455c117796550b79f444811db8ba2f69c57b646c784557febae6141bae5521e99e0a8d610356b0f501fea54980b59c84841db43ba7204f4557f0387e9d1203691d8e3362a7e4c6723de358a4010d7f31ecbec3fbfc61d1c75fc557ff5559028dc9ba50d75343c779b2f75e13a84a14662932fc67a486f263ca31a965560086000527f71f482bdabd1ea844d62c952b094e632959690d7448ca2aab34034ec98569358556200035a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526001602052604090205460ff1615620002725760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c72656164792070617573657200000000000000604482015260640160405180910390fd5b6001600160a01b038116600081815260016020818152604092839020805460ff191690921790915590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f8910160405180910390a150565b6000806000806000806000806000806101408b8d031215620002ee57600080fd5b8a516001600160a01b03811681146200030657600080fd5b809a505060208b0151985060408b0151975060608b0151965060808b0151955060a08b0151945060c08b0151935060e08b015192506101008b015191506101208b015190509295989b9194979a5092959850565b608051615e23620003a7600039600081816109a701528181610e08015281816110a501528181611c2501528181611ca0015281816121d9015281816130f201526146b80152615e236000f3fe6080604052600436106103905760003560e01c80636ea69d62116101dc57806390e360f811610102578063b4f7fa34116100a0578063eb505dd51161006f578063eb505dd514610af8578063eecefef814610b25578063f2fde38b14610b52578063fa52c7d814610b7257600080fd5b8063b4f7fa3414610a5f578063c8f9f98414610a7f578063dcfdc1e114610ab8578063e909156d14610ad857600080fd5b8063960dc08a116100dc578063960dc08a146109955780639b19251a146109c9578063a310624f146109f9578063acc62ccf14610a3f57600080fd5b806390e360f8146109255780639146f1101461095557806392bb243c1461097557600080fd5b806382dc1ec41161017a57806388d996e81161014957806388d996e8146108b257806389f9aab5146108d25780638a74d5fe146108e75780638da5cb5b1461090757600080fd5b806382dc1ec4146108515780638338f0e51461087157806383cfb318146108875780638456cb591461089d57600080fd5b806371bc0216116101b657806371bc0216146107cc5780637a50dbd2146107ec57806380f51c121461080c57806382d7b4b81461083c57600080fd5b80636ea69d62146107825780636ef8d66d146107a2578063715018a6146107b757600080fd5b8063410ae02c116102c1578063525eba211161025f578063682dbc221161022e578063682dbc22146106ec57806368706e541461070c5780636b2c0f551461072c5780636d3087831461074c57600080fd5b8063525eba21146106775780635c975abb146106975780635e593eff146106b657806365d5d420146106d657600080fd5b806347abfdbf1161029b57806347abfdbf146105fd57806349955e391461061d57806351508f0a1461063d57806351fb012d1461065d57600080fd5b8063410ae02c1461058457806346fbf68e146105a4578063473849bd146105dd57600080fd5b80632fa4d12b1161032e5780633985c4e6116103085780633985c4e6146104e45780633af32abf146105045780633f4ba83a1461054d5780634021d4d51461056257600080fd5b80632fa4d12b1461048257806336f1635f146104ba578063386c024a146104cf57600080fd5b8063145aa1161161036a578063145aa116146103fe5780631a2032571461041e5780631cfe4f0b1461043e578063291d95491461046257600080fd5b8063026e402b1461039c578063052d9e7e146103be57806310154bad146103de57600080fd5b3661039757005b600080fd5b3480156103a857600080fd5b506103bc6103b7366004615309565b610c10565b005b3480156103ca57600080fd5b506103bc6103d9366004615341565b610e90565b3480156103ea57600080fd5b506103bc6103f936600461535e565b610eeb565b34801561040a57600080fd5b506103bc610419366004615379565b610ff7565b34801561042a57600080fd5b506103bc610439366004615379565b6110cf565b34801561044a57600080fd5b506006545b6040519081526020015b60405180910390f35b34801561046e57600080fd5b506103bc61047d36600461535e565b611145565b34801561048e57600080fd5b50600c546104a2906001600160a01b031681565b6040516001600160a01b039091168152602001610459565b3480156104c657600080fd5b506103bc611246565b3480156104db57600080fd5b5061044f6115d4565b3480156104f057600080fd5b506103bc6104ff366004615420565b611601565b34801561051057600080fd5b5061053d61051f36600461535e565b6001600160a01b031660009081526002602052604090205460ff1690565b6040519015158152602001610459565b34801561055957600080fd5b506103bc611da7565b34801561056e57600080fd5b50610577611e10565b604051610459919061548c565b34801561059057600080fd5b5061044f61059f3660046154f3565b611f11565b3480156105b057600080fd5b5061053d6105bf36600461535e565b6001600160a01b031660009081526001602052604090205460ff1690565b3480156105e957600080fd5b506103bc6105f836600461535e565b611f50565b34801561060957600080fd5b5061053d61061836600461550e565b612258565b34801561062957600080fd5b506103bc61063836600461555d565b612312565b34801561064957600080fd5b506103bc61065836600461535e565b612474565b34801561066957600080fd5b5060035461053d9060ff1681565b34801561068357600080fd5b506103bc610692366004615578565b6124de565b3480156106a357600080fd5b50600054600160a01b900460ff1661053d565b3480156106c257600080fd5b506103bc6106d1366004615379565b612980565b3480156106e257600080fd5b5061044f60045481565b3480156106f857600080fd5b506103bc61070736600461566b565b612b99565b34801561071857600080fd5b506103bc61072736600461535e565b612bfc565b34801561073857600080fd5b506103bc61074736600461535e565b612c66565b34801561075857600080fd5b506104a261076736600461535e565b6009602052600090815260409020546001600160a01b031681565b34801561078e57600080fd5b50600d546104a2906001600160a01b031681565b3480156107ae57600080fd5b506103bc612cb7565b3480156107c357600080fd5b506103bc612cc0565b3480156107d857600080fd5b506103bc6107e736600461535e565b612d12565b3480156107f857600080fd5b506103bc61080736600461535e565b612e5a565b34801561081857600080fd5b5061053d61082736600461535e565b60016020526000908152604090205460ff1681565b34801561084857600080fd5b506103bc61308c565b34801561085d57600080fd5b506103bc61086c36600461535e565b613123565b34801561087d57600080fd5b5061044f600e5481565b34801561089357600080fd5b5061044f60055481565b3480156108a957600080fd5b506103bc613174565b3480156108be57600080fd5b506103bc6108cd366004615309565b6131db565b3480156108de57600080fd5b5060075461044f565b3480156108f357600080fd5b5061053d6109023660046157af565b6132d9565b34801561091357600080fd5b506000546001600160a01b03166104a2565b34801561093157600080fd5b5061053d610940366004615379565b600a6020526000908152604090205460ff1681565b34801561096157600080fd5b506103bc610970366004615827565b6134bd565b34801561098157600080fd5b506104a2610990366004615379565b61358b565b3480156109a157600080fd5b506104a27f000000000000000000000000000000000000000000000000000000000000000081565b3480156109d557600080fd5b5061053d6109e436600461535e565b60026020526000908152604090205460ff1681565b348015610a0557600080fd5b50610a32610a1436600461535e565b6001600160a01b031660009081526008602052604090205460ff1690565b60405161045991906158e0565b348015610a4b57600080fd5b506104a2610a5a366004615379565b6135b5565b348015610a6b57600080fd5b5061053d610a7a36600461535e565b6135c5565b348015610a8b57600080fd5b5061044f610a9a36600461535e565b6001600160a01b031660009081526008602052604090206001015490565b348015610ac457600080fd5b506103bc610ad3366004615309565b6135fd565b348015610ae457600080fd5b506103bc610af33660046158ee565b6136f5565b348015610b0457600080fd5b5061044f610b133660046154f3565b600b6020526000908152604090205481565b348015610b3157600080fd5b50610b45610b4036600461590a565b6137f8565b604051610459919061593d565b348015610b5e57600080fd5b506103bc610b6d36600461535e565b613af1565b348015610b7e57600080fd5b50610bfa610b8d36600461535e565b600860205260009081526040902080546001820154600283015460038401546004850154600686015460079096015460ff8616966101009096046001600160a01b0316959067ffffffffffffffff80821691680100000000000000008104821691600160801b909104168a565b6040516104599a999897969594939291906159dc565b600054600160a01b900460ff1615610c625760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064015b60405180910390fd5b33670de0b6b3a7640000821015610cbb5760405162461bcd60e51b815260206004820152601860248201527f4d696e696d616c20616d6f756e7420697320312043454c5200000000000000006044820152606401610c59565b6001600160a01b038316600090815260086020526040812090815460ff166003811115610cea57610cea6158a8565b1415610d385760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b6000610d4d8483600101548460020154613bbe565b6001600160a01b0384166000908152600584016020526040812080549293509183918391610d7c908490615a5e565b9250508190555081836002016000828254610d979190615a5e565b9250508190555084836001016000828254610db29190615a5e565b9091555060039050835460ff166003811115610dd057610dd06158a8565b1415610dfb578460046000828254610de89190615a5e565b90915550506001830154610dfb90613beb565b610e306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016853088613d0e565b6001830154815460408051928352602083019190915281018690526001600160a01b0380861691908816907f2e289e5a72f8e92e344eb866e0a32621f332835d2df2cf1f76e5a345b23cf1ea9060600160405180910390a3505050505050565b6000546001600160a01b03163314610ed85760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6003805460ff1916911515919091179055565b6000546001600160a01b03163314610f335760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6001600160a01b03811660009081526002602052604090205460ff1615610f9c5760405162461bcd60e51b815260206004820152601360248201527f416c72656164792077686974656c6973746564000000000000000000000000006044820152606401610c59565b6001600160a01b038116600081815260026020908152604091829020805460ff1916600117905590519182527fee1504a83b6d4a361f4c1dc78ab59bfa30d6a3b6612c403e86bb01ef2984295f91015b60405180910390a150565b600054600160a01b900460ff166110505760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c59565b6000546001600160a01b031633146110985760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6110cc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383613da6565b50565b6000546001600160a01b031633146111175760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6008600052600b6020527f71f482bdabd1ea844d62c952b094e632959690d7448ca2aab34034ec9856935855565b6000546001600160a01b0316331461118d5760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6001600160a01b03811660009081526002602052604090205460ff166111f55760405162461bcd60e51b815260206004820152600f60248201527f4e6f742077686974656c697374656400000000000000000000000000000000006044820152606401610c59565b6001600160a01b038116600081815260026020908152604091829020805460ff1916905590519182527f270d9b30cf5b0793bbfd54c9d5b94aeb49462b8148399000265144a8722da6b69101610fec565b336000818152600960205260409020546001600160a01b03161561127f5750336000908152600960205260409020546001600160a01b03165b6001600160a01b03811660009081526008602052604090206001815460ff1660038111156112af576112af6158a8565b14806112d057506002815460ff1660038111156112ce576112ce6158a8565b145b61131c5760405162461bcd60e51b815260206004820152601860248201527f496e76616c69642076616c696461746f722073746174757300000000000000006044820152606401610c59565b600781015467ffffffffffffffff1643101561137a5760405162461bcd60e51b815260206004820152601660248201527f426f6e6420626c6f636b206e6f742072656163686564000000000000000000006044820152606401610c59565b6005544310156113cc5760405162461bcd60e51b815260206004820152601b60248201527f546f6f206672657175656e742076616c696461746f7220626f6e6400000000006044820152606401610c59565b6007600052600b6020527ff5559028dc9ba50d75343c779b2f75e13a84a14662932fc67a486f263ca31a96546114029043615a5e565b600555611410826001612258565b61145c5760405162461bcd60e51b815260206004820152601360248201527f4e6f742068617665206d696e20746f6b656e73000000000000000000000000006044820152606401610c59565b6003600052600b6020527f64c15cc42be7899b001f818cf4433057002112c418d1d3a67cd5cb453051d33e546007548111156114ad5761149b83613dd6565b6114a88260010154613beb565b505050565b6000196000805b83811015611562578260086000600784815481106114d4576114d4615a76565b60009182526020808320909101546001600160a01b03168352820192909252604001902060010154101561155057809150600860006007838154811061151c5761151c615a76565b60009182526020808320909101546001600160a01b0316835282019290925260400190206001015492508261155057611562565b8061155a81615a8c565b9150506114b4565b50818460010154116115b65760405162461bcd60e51b815260206004820152601360248201527f496e73756666696369656e7420746f6b656e73000000000000000000000000006044820152606401610c59565b6115c08582613e2a565b6115cd8460010154613beb565b5050505050565b6000600360045460026115e79190615aa7565b6115f19190615ac6565b6115fc906001615a5e565b905090565b600054600160a01b900460ff161561164e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c59565b600046306040516020016116a492919091825260601b6bffffffffffffffffffffffff191660208201527f536c617368000000000000000000000000000000000000000000000000000000603482015260390190565b6040516020818303038152906040528051906020012090506116ee8186866040516020016116d493929190615ae8565b60408051601f198184030181529190526109028486615b02565b50600061173086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613ea592505050565b9050806060015167ffffffffffffffff16421061178f5760405162461bcd60e51b815260206004820152600d60248201527f536c6173682065787069726564000000000000000000000000000000000000006044820152606401610c59565b620f4240816040015167ffffffffffffffff1611156117f05760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420736c61736820666163746f720000000000000000000000006044820152606401610c59565b6008600052600b6020527f71f482bdabd1ea844d62c952b094e632959690d7448ca2aab34034ec9856935854604082015167ffffffffffffffff1611156118795760405162461bcd60e51b815260206004820152601760248201527f457863656564206d617820736c61736820666163746f720000000000000000006044820152606401610c59565b60208082015167ffffffffffffffff166000908152600a909152604090205460ff16156118e85760405162461bcd60e51b815260206004820152601060248201527f5573656420736c617368206e6f6e6365000000000000000000000000000000006044820152606401610c59565b60208082015167ffffffffffffffff166000908152600a82526040808220805460ff1916600117905583516001600160a01b0381168352600890935290206003815460ff16600381111561193e5761193e6158a8565b148061195f57506002815460ff16600381111561195d5761195d6158a8565b145b6119ab5760405162461bcd60e51b815260206004820152601860248201527f496e76616c69642076616c696461746f722073746174757300000000000000006044820152606401610c59565b6000620f4240846040015167ffffffffffffffff1683600101546119cf9190615aa7565b6119d99190615ac6565b9050808260010160008282546119ef9190615b0f565b9091555060039050825460ff166003811115611a0d57611a0d6158a8565b1415611a5c578060046000828254611a259190615b0f565b9091555050608084015167ffffffffffffffff16151580611a4e5750611a4c836001612258565b155b15611a5c57611a5c83614117565b6002825460ff166003811115611a7457611a746158a8565b148015611a8f57506000846080015167ffffffffffffffff16115b15611ad2576080840151611aad9067ffffffffffffffff1643615a5e565b60078301805467ffffffffffffffff191667ffffffffffffffff929092169190911790555b60006001600160a01b0316836001600160a01b03167f2e289e5a72f8e92e344eb866e0a32621f332835d2df2cf1f76e5a345b23cf1ea8460010154600085611b1990615b26565b6040805193845260208401929092529082015260600160405180910390a36000620f4240856040015167ffffffffffffffff168460030154611b5b9190615aa7565b611b659190615ac6565b905080836003016000828254611b7b9190615b0f565b90915550611b8b90508183615a5e565b91506000805b8660a0015151811015611d255760008760a001518281518110611bb657611bb6615a76565b6020026020010151905084816020015184611bd19190615a5e565b1115611be757611be18386615b0f565b60208201525b602081015115611d12576020810151611c009084615a5e565b81519093506001600160a01b0316611c8b576020810151611c4d906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016903390613da6565b60208082015160405190815233917fb1375221b23a15d2f6887c7dbdc6745a07d9a5245076d51fb41879590ebbd2a3910160405180910390a2611d12565b80516020820151611cc6916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691613da6565b80600001516001600160a01b03167fb1375221b23a15d2f6887c7dbdc6745a07d9a5245076d51fb41879590ebbd2a38260200151604051611d0991815260200190565b60405180910390a25b5080611d1d81615a8c565b915050611b91565b50611d308184615b0f565b600e6000828254611d419190615a5e565b90915550506020808701516040805167ffffffffffffffff90921682529181018590526001600160a01b038716917f10863f35bc5db9fda133333468bf7b1ceaaa88cb4263c061f890f97b79bf9008910160405180910390a25050505050505050505050565b3360009081526001602052604090205460ff16611e065760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610c59565b611e0e61427d565b565b60075460609060009067ffffffffffffffff811115611e3157611e316155b4565b604051908082528060200260200182016040528015611e7657816020015b6040805180820190915260008082526020820152815260200190600190039081611e4f5790505b50905060005b600754811015611f0b57600060078281548110611e9b57611e9b615a76565b60009182526020808320909101546040805180820182526001600160a01b039092168083528085526008845293206001015491810191909152845191925090849084908110611eec57611eec615a76565b6020026020010181905250508080611f0390615a8c565b915050611e7c565b50919050565b6000600b6000836008811115611f2957611f296158a8565b6008811115611f3a57611f3a6158a8565b8152602001908152602001600020549050919050565b6001600160a01b03811660009081526008602052604081203391815460ff166003811115611f8057611f806158a8565b1415611fce5760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b6001600160a01b03821660009081526005820160209081526040822060028352600b9091527fa50eece07c7db1631545c0069bd8f5f54d5935e215d59097edf258a44ba916345483549192909160019060ff166003811115612032576120326158a8565b60028501549114915063ffffffff1660005b600285015463ffffffff640100000000909104811690831610156120f6578280612094575063ffffffff821660009081526001808701602052604090912001544390612091908690615a5e565b11155b156120df5763ffffffff821660009081526001860160205260409020546120bb9082615a5e565b63ffffffff83166000908152600180880160205260408220828155015590506120e4565b6120f6565b816120ee81615b43565b925050612044565b60028501805463ffffffff191663ffffffff8416179055806121805760405162461bcd60e51b815260206004820152602560248201527f4e6f20756e64656c65676174696f6e20726561647920746f20626520636f6d7060448201527f6c657465640000000000000000000000000000000000000000000000000000006064820152608401610c59565b60006121958288600301548960040154614323565b9050818760040160008282546121ab9190615b0f565b92505081905550808760030160008282546121c69190615b0f565b9091555061220090506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168983613da6565b876001600160a01b0316896001600160a01b03167f4d10bd049775c77bd7f255195afba5088028ecb3c7c277d393ccff7934f2f92c8360405161224591815260200190565b60405180910390a3505050505050505050565b6001600160a01b03821660009081526008602090815260408220600181015460048452600b9092527f12d0c11577e2f0950f57c455c117796550b79f444811db8ba2f69c57b646c784549091908110156122b75760009250505061230c565b8315612305576001600160a01b038516600090815260058301602052604081205460028401546122e991908490614323565b90508260060154811015612303576000935050505061230c565b505b6001925050505b92915050565b33600081815260086020526040812090815460ff166003811115612338576123386158a8565b14156123865760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b6127108367ffffffffffffffff1611156123e25760405162461bcd60e51b815260206004820152601060248201527f496e76616c6964206e65772072617465000000000000000000000000000000006044820152606401610c59565b60078101805467ffffffffffffffff60801b1916600160801b67ffffffffffffffff8616908102919091179091556040805160208101929092526001600160a01b038416917f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c910160408051601f198184030181529082905261246791600090615bbf565b60405180910390a2505050565b6000546001600160a01b031633146124bc5760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b600054600160a01b900460ff161561252b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c59565b60035460ff1615612595573360009081526002602052604090205460ff166125955760405162461bcd60e51b815260206004820152601960248201527f43616c6c6572206973206e6f742077686974656c6973746564000000000000006044820152606401610c59565b33600081815260086020526040812090815460ff1660038111156125bb576125bb6158a8565b146126085760405162461bcd60e51b815260206004820152601860248201527f56616c696461746f7220697320696e697469616c697a656400000000000000006044820152606401610c59565b6001600160a01b03851660009081526008602052604081205460ff166003811115612635576126356158a8565b146126825760405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206f746865722076616c696461746f72000000000000006044820152606401610c59565b6001600160a01b0382811660009081526009602052604090205416156126ea5760405162461bcd60e51b815260206004820152601960248201527f56616c696461746f72206973206f74686572207369676e6572000000000000006044820152606401610c59565b6001600160a01b0385811660009081526009602052604090205416156127525760405162461bcd60e51b815260206004820152601360248201527f5369676e657220616c72656164792075736564000000000000000000000000006044820152606401610c59565b6127108367ffffffffffffffff1611156127ae5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420636f6d6d697373696f6e20726174650000000000000000006044820152606401610c59565b6005600052600b6020527febae6141bae5521e99e0a8d610356b0f501fea54980b59c84841db43ba7204f4548410156128295760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e74206d696e2073656c662064656c65676174696f6e6044820152606401610c59565b80547fffffffffffffffffffffff0000000000000000000000000000000000000000001660ff196101006001600160a01b03888116918202929092169290921760019081178455600680850188905560078501805467ffffffffffffffff60801b1916600160801b67ffffffffffffffff8a1602179055805491820190557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0180546001600160a01b031990811692861692831790915560009283526009602052604090922080549092161790556129018285610c10565b604080516001600160a01b03878116602083015291810186905267ffffffffffffffff85166060820152908316907f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c9060800160408051601f198184030181529082905261297191600090615c1e565b60405180910390a25050505050565b33600081815260086020526040812090815460ff1660038111156129a6576129a66158a8565b14156129f45760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b6005600052600b6020527febae6141bae5521e99e0a8d610356b0f501fea54980b59c84841db43ba7204f454831015612a6f5760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e74206d696e2073656c662064656c65676174696f6e6044820152606401610c59565b8060060154831015612b3c576003815460ff166003811115612a9357612a936158a8565b1415612ae15760405162461bcd60e51b815260206004820152601360248201527f56616c696461746f7220697320626f6e646564000000000000000000000000006044820152606401610c59565b6006600052600b6020527f0387e9d1203691d8e3362a7e4c6723de358a4010d7f31ecbec3fbfc61d1c75fc54612b179043615a5e565b60078201805467ffffffffffffffff191667ffffffffffffffff929092169190911790555b6006810183905560408051602081018590526001600160a01b038416917f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c910160408051601f198184030181529082905261246791600090615c4c565b612ba7876109028789615b02565b612bf35760405162461bcd60e51b815260206004820152601560248201527f4661696c656420746f20766572696679207369677300000000000000000000006044820152606401610c59565b50505050505050565b6000546001600160a01b03163314612c445760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314612cae5760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6110cc8161433c565b611e0e3361433c565b6000546001600160a01b03163314612d085760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b611e0e60006143f5565b6001600160a01b03811660009081526008602052604090206002815460ff166003811115612d4257612d426158a8565b14612d8f5760405162461bcd60e51b815260206004820152601760248201527f56616c696461746f72206e6f7420756e626f6e64696e670000000000000000006044820152606401610c59565b600781015468010000000000000000900467ffffffffffffffff16431015612df95760405162461bcd60e51b815260206004820152601860248201527f556e626f6e6420626c6f636b206e6f74207265616368656400000000000000006044820152606401610c59565b805460ff1916600190811782556007820180546fffffffffffffffff0000000000000000191690555b6040516001600160a01b038416907fd5e59fa85493a77fb57f6bf9080f2f71fde9de0eadc62b27b43b6263f3f1f59a90600090a35050565b33600081815260086020526040812090815460ff166003811115612e8057612e806158a8565b1415612ece5760405162461bcd60e51b815260206004820152601960248201527f56616c696461746f72206e6f7420696e697469616c697a6564000000000000006044820152606401610c59565b6001600160a01b038381166000908152600960205260409020541615612f365760405162461bcd60e51b815260206004820152601360248201527f5369676e657220616c72656164792075736564000000000000000000000000006044820152606401610c59565b816001600160a01b0316836001600160a01b031614612fc9576001600160a01b03831660009081526008602052604081205460ff166003811115612f7c57612f7c6158a8565b14612fc95760405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206f746865722076616c696461746f72000000000000006044820152606401610c59565b8054610100908190046001600160a01b03908116600090815260096020908152604080832080546001600160a01b031990811690915586547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1689861696870217875585845292819020805490931693871693841790925581519081019390935290917f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c910160408051601f198184030181529082905261246791600090615c93565b6000600e54116130de5760405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f20636f6c6c65637400000000000000000000000000006044820152606401610c59565b600d54600e5461311c916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811692911690613da6565b6000600e55565b6000546001600160a01b0316331461316b5760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6110cc81614445565b3360009081526001602052604090205460ff166131d35760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610c59565b611e0e614503565b670de0b6b3a76400008110156132335760405162461bcd60e51b815260206004820152601960248201527f4d696e696d616c20616d6f756e742069732031207368617265000000000000006044820152606401610c59565b6001600160a01b038216600090815260086020526040812090815460ff166003811115613262576132626158a8565b14156132b05760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b60006132c58383600101548460020154614323565b90506132d38285838661458b565b50505050565b60008061333a84805190602001206040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050600080806133486115d4565b905060005b865181101561347457600061338488838151811061336d5761336d615a76565b60200260200101518761492e90919063ffffffff16565b9050836001600160a01b0316816001600160a01b0316116133e75760405162461bcd60e51b815260206004820152601e60248201527f5369676e657273206e6f7420696e20617363656e64696e67206f7264657200006044820152606401610c59565b6001600160a01b038082166000908152600960209081526040808320549093168252600890522090935083906003815460ff16600381111561342b5761342b6158a8565b14613437575050613462565b60018101546134469087615a5e565b955083861061345f57600197505050505050505061230c565b50505b8061346c81615a8c565b91505061334d565b5060405162461bcd60e51b815260206004820152601260248201527f51756f72756d206e6f74207265616368656400000000000000000000000000006044820152606401610c59565b6001600160a01b038516600090815260086020526040812090815460ff1660038111156134ec576134ec6158a8565b141561353a5760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b856001600160a01b03167f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c868686863360405161357b959493929190615d03565b60405180910390a2505050505050565b6006818154811061359b57600080fd5b6000918252602090912001546001600160a01b0316905081565b6007818154811061359b57600080fd5b600060036001600160a01b03831660009081526008602052604090205460ff1660038111156135f6576135f66158a8565b1492915050565b670de0b6b3a76400008110156136555760405162461bcd60e51b815260206004820152601860248201527f4d696e696d616c20616d6f756e7420697320312043454c5200000000000000006044820152606401610c59565b6001600160a01b038216600090815260086020526040812090815460ff166003811115613684576136846158a8565b14156136d25760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b60006136e78383600101548460020154613bbe565b90506132d38285858461458b565b600c546001600160a01b0316331461374f5760405162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f7420676f7620636f6e74726163740000000000006044820152606401610c59565b6003826008811115613763576137636158a8565b14156137bb576007548110156137bb5760405162461bcd60e51b815260206004820152600d60248201527f696e76616c69642076616c7565000000000000000000000000000000000000006044820152606401610c59565b80600b60008460088111156137d2576137d26158a8565b60088111156137e3576137e36158a8565b81526020810191909152604001600020555050565b61383a6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016060815260200160008152602001600081525090565b6001600160a01b038084166000908152600860209081526040808320938616835260058401909152812080546001840154600285015492939261387e929190614323565b60026000908152600b6020527fa50eece07c7db1631545c0069bd8f5f54d5935e215d59097edf258a44ba916345485549293509091829190829060019060ff1660038111156138cf576138cf6158a8565b6002880154911491506000906138f69063ffffffff80821691640100000000900416615d46565b63ffffffff16905060008167ffffffffffffffff811115613919576139196155b4565b60405190808252806020026020018201604052801561395e57816020015b60408051808201909152600080825260208201528152602001906001900390816139375790505b50905060005b82811015613a7557600289015460018a01906000906139899063ffffffff1684615a5e565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250508282815181106139c8576139c8615a76565b60200260200101819052508181815181106139e5576139e5615a76565b602002602001015160000151876139fc9190615a5e565b96508380613a3257504385838381518110613a1957613a19615a76565b602002602001015160200151613a2f9190615a5e565b11155b15613a6357818181518110613a4957613a49615a76565b60200260200101516000015186613a609190615a5e565b95505b80613a6d81615a8c565b915050613964565b506000613a8b878b600301548c60040154614323565b90506000613aa2878c600301548d60040154614323565b90506040518060c001604052808f6001600160a01b031681526020018a81526020018b600001548152602001848152602001838152602001828152509b50505050505050505050505092915050565b6000546001600160a01b03163314613b395760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6001600160a01b038116613bb55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610c59565b6110cc816143f5565b600082613bcc575082613be4565b82613bd78386615aa7565b613be19190615ac6565b90505b9392505050565b6007546002811480613bfd5750806003145b15613c8257613c0a6115d4565b8210613c7e5760405162461bcd60e51b815260206004820152602e60248201527f53696e676c652076616c696461746f722073686f756c64206e6f74206861766560448201527f2071756f72756d20746f6b656e730000000000000000000000000000000000006064820152608401610c59565b5050565b6003811115613c7e576003600454613c9a9190615ac6565b8210613c7e5760405162461bcd60e51b815260206004820152602b60248201527f53696e676c652076616c696461746f722073686f756c64206e6f74206861766560448201527f20312f3320746f6b656e730000000000000000000000000000000000000000006064820152608401610c59565b6040516001600160a01b03808516602483015283166044820152606481018290526132d39085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526149d2565b6040516001600160a01b0383166024820152604481018290526114a890849063a9059cbb60e01b90606401613d42565b600780546001810182556000919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319166001600160a01b0383161790556110cc81614ab7565b613e5a60078281548110613e4057613e40615a76565b6000918252602090912001546001600160a01b0316614b1d565b8160078281548110613e6e57613e6e615a76565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550613c7e82614ab7565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a084015283518085019094528184528301849052909190613ef4826006614bc4565b905080600681518110613f0957613f09615a76565b602002602001015167ffffffffffffffff811115613f2957613f296155b4565b604051908082528060200260200182016040528015613f6e57816020015b6040805180820190915260008082526020820152815260200190600190039081613f475790505b508360a00181905250600081600681518110613f8c57613f8c615a76565b6020026020010181815250506000805b6020840151518451101561410e57613fb384614c7e565b90925090508160011415613fe257613fd2613fcd85614cb8565b614d75565b6001600160a01b03168552613f9c565b816002141561400857613ff484614d80565b67ffffffffffffffff166020860152613f9c565b816003141561402e5761401a84614d80565b67ffffffffffffffff166040860152613f9c565b81600414156140545761404084614d80565b67ffffffffffffffff166060860152613f9c565b816005141561407a5761406684614d80565b67ffffffffffffffff166080860152613f9c565b81600614156140ff5761409461408f85614cb8565b614e02565b8560a00151846006815181106140ac576140ac615a76565b6020026020010151815181106140c4576140c4615a76565b6020026020010181905250826006815181106140e2576140e2615a76565b6020026020010180518091906140f790615a8c565b905250613f9c565b6141098482614ea9565b613f9c565b50505050919050565b60075460009061412990600190615b0f565b905060005b60075481101561423457826001600160a01b03166007828154811061415557614155615a76565b6000918252602090912001546001600160a01b0316141561422257818110156141e6576007828154811061418b5761418b615a76565b600091825260209091200154600780546001600160a01b0390921691839081106141b7576141b7615a76565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b60078054806141f7576141f7615d6b565b600082815260209020810160001990810180546001600160a01b03191690550190556114a883614b1d565b8061422c81615a8c565b91505061412e565b5060405162461bcd60e51b815260206004820152601460248201527f4e6f7420626f6e6465642076616c696461746f720000000000000000000000006044820152606401610c59565b600054600160a01b900460ff166142d65760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c59565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600081614331575082613be4565b81613bd78486615aa7565b6001600160a01b03811660009081526001602052604090205460ff166143a45760405162461bcd60e51b815260206004820152601560248201527f4163636f756e74206973206e6f742070617573657200000000000000000000006044820152606401610c59565b6001600160a01b038116600081815260016020908152604091829020805460ff1916905590519182527fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e9101610fec565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526001602052604090205460ff16156144ae5760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c726561647920706175736572000000000000006044820152606401610c59565b6001600160a01b038116600081815260016020818152604092839020805460ff191690921790915590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f89101610fec565b600054600160a01b900460ff16156145505760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c59565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586143063390565b33600081815260058601602052604081208054909184918391906145b0908490615b0f565b92505081905550828660020160008282546145cb9190615b0f565b92505081905550838660010160008282546145e69190615b0f565b9091555050600286015460018701541480159061460557508054600210155b1561462a578054600287018054600090614620908490615b0f565b9091555050600081555b8054158061464157508054670de0b6b3a764000011155b61468d5760405162461bcd60e51b815260206004820152601b60248201527f6e6f7420656e6f7567682072656d61696e696e672073686172657300000000006044820152606401610c59565b6001865460ff1660038111156146a5576146a56158a8565b1415614733576146df6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168386613da6565b816001600160a01b0316856001600160a01b03167f4d10bd049775c77bd7f255195afba5088028ecb3c7c277d393ccff7934f2f92c8660405161472491815260200190565b60405180910390a350506132d3565b6003865460ff16600381111561474b5761474b6158a8565b14156147955783600460008282546147639190615b0f565b9250508190555061478885866001600160a01b0316846001600160a01b031614612258565b6147955761479585614117565b6002810154600a906147b89063ffffffff80821691640100000000900416615d46565b63ffffffff161061480b5760405162461bcd60e51b815260206004820152601f60248201527f457863656564206d617820756e64656c65676174696f6e20656e7472696573006044820152606401610c59565b60006148208588600301548960040154613bbe565b9050808760040160008282546148369190615a5e565b92505081905550848760030160008282546148519190615a5e565b909155505060028201805463ffffffff6401000000009182900481166000908152600180870160205260409091208581554391810191909155835490939290041690600461489e83615b43565b91906101000a81548163ffffffff021916908363ffffffff16021790555050836001600160a01b0316876001600160a01b03167f2e289e5a72f8e92e344eb866e0a32621f332835d2df2cf1f76e5a345b23cf1ea8a6001015486600001548a61490690615b26565b6040805193845260208401929092529082015260600160405180910390a35050505050505050565b60008151604114156149625760208201516040830151606084015160001a61495886828585614f1b565b935050505061230c565b81516040141561498a57602082015160408301516149818583836150c4565b9250505061230c565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c59565b6000614a27826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166151079092919063ffffffff16565b8051909150156114a85780806020019051810190614a459190615d81565b6114a85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610c59565b6001600160a01b0381166000908152600860205260408120805460ff191660031781556007810180546fffffffffffffffff00000000000000001916905560018101546004805492939192909190614b10908490615a5e565b9091555060039050612e22565b6001600160a01b03811660009081526008602090815260408220805460ff191660029081178255909252600b90527fa50eece07c7db1631545c0069bd8f5f54d5935e215d59097edf258a44ba9163454614b779043615a5e565b8160070160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550806001015460046000828254614bb79190615b0f565b9091555060029050612e22565b8151606090614bd4836001615a5e565b67ffffffffffffffff811115614bec57614bec6155b4565b604051908082528060200260200182016040528015614c15578160200160208202803683370190505b5091506000805b60208601515186511015614c7557614c3386614c7e565b80925081935050506001848381518110614c4f57614c4f615a76565b60200260200101818151614c639190615a5e565b905250614c708682614ea9565b614c1c565b50509092525090565b6000806000614c8c84614d80565b9050614c99600882615ac6565b9250806007166005811115614cb057614cb06158a8565b915050915091565b60606000614cc583614d80565b90506000818460000151614cd99190615a5e565b9050836020015151811115614ced57600080fd5b8167ffffffffffffffff811115614d0657614d066155b4565b6040519080825280601f01601f191660200182016040528015614d30576020820181803683370190505b50602080860151865192955091818601919083010160005b85811015614d6a578181015183820152614d63602082615a5e565b9050614d48565b505050935250919050565b600061230c82615116565b602080820151825181019091015160009182805b600a811015614dfc5783811a9150614dad816007615aa7565b82607f16901b851794508160801660001415614dea57614dce816001615a5e565b86518790614ddd908390615a5e565b9052509395945050505050565b80614df481615a8c565b915050614d94565b50600080fd5b6040805180820182526000808252602080830182905283518085019094528184528301849052909190805b60208301515183511015614ea157614e4483614c7e565b90925090508160011415614e6e57614e5e613fcd84614cb8565b6001600160a01b03168452614e2d565b8160021415614e9257614e88614e8384614cb8565b61513e565b6020850152614e2d565b614e9c8382614ea9565b614e2d565b505050919050565b6000816005811115614ebd57614ebd6158a8565b1415614ecc576114a882614d80565b6002816005811115614ee057614ee06158a8565b1415610397576000614ef183614d80565b90508083600001818151614f059190615a5e565b905250602083015151835111156114a857600080fd5b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115614f985760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c59565b8360ff16601b1480614fad57508360ff16601c145b6150045760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610c59565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015615058573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166150bb5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c59565b95945050505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821660ff83901c601b016150fd86828785614f1b565b9695505050505050565b6060613be18484600085615175565b6000815160141461512657600080fd5b50602001516c01000000000000000000000000900490565b600060208251111561514f57600080fd5b60208201519050815160206151649190615b0f565b61516f906008615aa7565b1c919050565b6060824710156151ed5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610c59565b843b61523b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c59565b600080866001600160a01b031685876040516152579190615d9e565b60006040518083038185875af1925050503d8060008114615294576040519150601f19603f3d011682016040523d82523d6000602084013e615299565b606091505b50915091506152a98282866152b4565b979650505050505050565b606083156152c3575081613be4565b8251156152d35782518084602001fd5b8160405162461bcd60e51b8152600401610c599190615dba565b80356001600160a01b038116811461530457600080fd5b919050565b6000806040838503121561531c57600080fd5b615325836152ed565b946020939093013593505050565b80151581146110cc57600080fd5b60006020828403121561535357600080fd5b8135613be481615333565b60006020828403121561537057600080fd5b613be4826152ed565b60006020828403121561538b57600080fd5b5035919050565b60008083601f8401126153a457600080fd5b50813567ffffffffffffffff8111156153bc57600080fd5b6020830191508360208285010111156153d457600080fd5b9250929050565b60008083601f8401126153ed57600080fd5b50813567ffffffffffffffff81111561540557600080fd5b6020830191508360208260051b85010111156153d457600080fd5b6000806000806040858703121561543657600080fd5b843567ffffffffffffffff8082111561544e57600080fd5b61545a88838901615392565b9096509450602087013591508082111561547357600080fd5b50615480878288016153db565b95989497509550505050565b602080825282518282018190526000919060409081850190868401855b828110156154d757815180516001600160a01b031685528601518685015292840192908501906001016154a9565b5091979650505050505050565b80356009811061530457600080fd5b60006020828403121561550557600080fd5b613be4826154e4565b6000806040838503121561552157600080fd5b61552a836152ed565b9150602083013561553a81615333565b809150509250929050565b803567ffffffffffffffff8116811461530457600080fd5b60006020828403121561556f57600080fd5b613be482615545565b60008060006060848603121561558d57600080fd5b615596846152ed565b9250602084013591506155ab60408501615545565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156155f3576155f36155b4565b604052919050565b600082601f83011261560c57600080fd5b813567ffffffffffffffff811115615626576156266155b4565b615639601f8201601f19166020016155ca565b81815284602083860101111561564e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060006080888a03121561568657600080fd5b873567ffffffffffffffff8082111561569e57600080fd5b6156aa8b838c016155fb565b985060208a01359150808211156156c057600080fd5b6156cc8b838c016153db565b909850965060408a01359150808211156156e557600080fd5b6156f18b838c016153db565b909650945060608a013591508082111561570a57600080fd5b506157178a828b016153db565b989b979a50959850939692959293505050565b600067ffffffffffffffff80841115615745576157456155b4565b8360051b60206157568183016155ca565b8681529350908401908084018783111561576f57600080fd5b855b838110156157a3578035858111156157895760008081fd5b6157958a828a016155fb565b835250908201908201615771565b50505050509392505050565b600080604083850312156157c257600080fd5b823567ffffffffffffffff808211156157da57600080fd5b6157e6868387016155fb565b935060208501359150808211156157fc57600080fd5b508301601f8101851361580e57600080fd5b61581d8582356020840161572a565b9150509250929050565b60008060008060006060868803121561583f57600080fd5b615848866152ed565b9450602086013567ffffffffffffffff8082111561586557600080fd5b61587189838a01615392565b9096509450604088013591508082111561588a57600080fd5b5061589788828901615392565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b600481106158dc57634e487b7160e01b600052602160045260246000fd5b9052565b6020810161230c82846158be565b6000806040838503121561590157600080fd5b615325836154e4565b6000806040838503121561591d57600080fd5b615926836152ed565b9150615934602084016152ed565b90509250929050565b6000602080835260e083016001600160a01b038551168285015281850151604081818701528087015160608701526060870151915060c06080870152828251808552610100880191508584019450600093505b808410156159b95784518051835286015186830152938501936001939093019290820190615990565b50608088015160a088015260a088015160c0880152809550505050505092915050565b61014081016159eb828d6158be565b6001600160a01b039a909a16602082015260408101989098526060880196909652608087019490945260a086019290925260c085015267ffffffffffffffff90811660e08501529081166101008401521661012090910152919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115615a7157615a71615a48565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600019821415615aa057615aa0615a48565b5060010190565b6000816000190483118215151615615ac157615ac1615a48565b500290565b600082615ae357634e487b7160e01b600052601260045260246000fd5b500490565b838152818360208301376000910160200190815292915050565b6000613be436848461572a565b600082821015615b2157615b21615a48565b500390565b6000600160ff1b821415615b3c57615b3c615a48565b5060000390565b600063ffffffff80831681811415615b5d57615b5d615a48565b6001019392505050565b60005b83811015615b82578181015183820152602001615b6a565b838111156132d35750506000910152565b60008151808452615bab816020860160208601615b67565b601f01601f19169290920160200192915050565b60608152600a60608201527f636f6d6d697373696f6e00000000000000000000000000000000000000000000608082015260a060208201526000615c0660a0830185615b93565b90506001600160a01b03831660408301529392505050565b6060815260046060820152631a5b9a5d60e21b608082015260a060208201526000615c0660a0830185615b93565b60608152601360608201527f6d696e2d73656c662d64656c65676174696f6e00000000000000000000000000608082015260a060208201526000615c0660a0830185615b93565b60608152600660608201527f7369676e65720000000000000000000000000000000000000000000000000000608082015260a060208201526000615c0660a0830185615b93565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b606081526000615d17606083018789615cda565b8281036020840152615d2a818688615cda565b9150506001600160a01b03831660408301529695505050505050565b600063ffffffff83811690831681811015615d6357615d63615a48565b039392505050565b634e487b7160e01b600052603160045260246000fd5b600060208284031215615d9357600080fd5b8151613be481615333565b60008251615db0818460208701615b67565b9190910192915050565b602081526000613be46020830184615b9356fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a26469706673582212201e41fbe148ca51c46448ba41ffc013bb54a58fc4e688ebf2d9e4fc84d2b1e7d164736f6c634300080900330000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c6670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022600000000000000000000000000000000000000000000000000000000000008a7000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000000000000000019c800000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106103905760003560e01c80636ea69d62116101dc57806390e360f811610102578063b4f7fa34116100a0578063eb505dd51161006f578063eb505dd514610af8578063eecefef814610b25578063f2fde38b14610b52578063fa52c7d814610b7257600080fd5b8063b4f7fa3414610a5f578063c8f9f98414610a7f578063dcfdc1e114610ab8578063e909156d14610ad857600080fd5b8063960dc08a116100dc578063960dc08a146109955780639b19251a146109c9578063a310624f146109f9578063acc62ccf14610a3f57600080fd5b806390e360f8146109255780639146f1101461095557806392bb243c1461097557600080fd5b806382dc1ec41161017a57806388d996e81161014957806388d996e8146108b257806389f9aab5146108d25780638a74d5fe146108e75780638da5cb5b1461090757600080fd5b806382dc1ec4146108515780638338f0e51461087157806383cfb318146108875780638456cb591461089d57600080fd5b806371bc0216116101b657806371bc0216146107cc5780637a50dbd2146107ec57806380f51c121461080c57806382d7b4b81461083c57600080fd5b80636ea69d62146107825780636ef8d66d146107a2578063715018a6146107b757600080fd5b8063410ae02c116102c1578063525eba211161025f578063682dbc221161022e578063682dbc22146106ec57806368706e541461070c5780636b2c0f551461072c5780636d3087831461074c57600080fd5b8063525eba21146106775780635c975abb146106975780635e593eff146106b657806365d5d420146106d657600080fd5b806347abfdbf1161029b57806347abfdbf146105fd57806349955e391461061d57806351508f0a1461063d57806351fb012d1461065d57600080fd5b8063410ae02c1461058457806346fbf68e146105a4578063473849bd146105dd57600080fd5b80632fa4d12b1161032e5780633985c4e6116103085780633985c4e6146104e45780633af32abf146105045780633f4ba83a1461054d5780634021d4d51461056257600080fd5b80632fa4d12b1461048257806336f1635f146104ba578063386c024a146104cf57600080fd5b8063145aa1161161036a578063145aa116146103fe5780631a2032571461041e5780631cfe4f0b1461043e578063291d95491461046257600080fd5b8063026e402b1461039c578063052d9e7e146103be57806310154bad146103de57600080fd5b3661039757005b600080fd5b3480156103a857600080fd5b506103bc6103b7366004615309565b610c10565b005b3480156103ca57600080fd5b506103bc6103d9366004615341565b610e90565b3480156103ea57600080fd5b506103bc6103f936600461535e565b610eeb565b34801561040a57600080fd5b506103bc610419366004615379565b610ff7565b34801561042a57600080fd5b506103bc610439366004615379565b6110cf565b34801561044a57600080fd5b506006545b6040519081526020015b60405180910390f35b34801561046e57600080fd5b506103bc61047d36600461535e565b611145565b34801561048e57600080fd5b50600c546104a2906001600160a01b031681565b6040516001600160a01b039091168152602001610459565b3480156104c657600080fd5b506103bc611246565b3480156104db57600080fd5b5061044f6115d4565b3480156104f057600080fd5b506103bc6104ff366004615420565b611601565b34801561051057600080fd5b5061053d61051f36600461535e565b6001600160a01b031660009081526002602052604090205460ff1690565b6040519015158152602001610459565b34801561055957600080fd5b506103bc611da7565b34801561056e57600080fd5b50610577611e10565b604051610459919061548c565b34801561059057600080fd5b5061044f61059f3660046154f3565b611f11565b3480156105b057600080fd5b5061053d6105bf36600461535e565b6001600160a01b031660009081526001602052604090205460ff1690565b3480156105e957600080fd5b506103bc6105f836600461535e565b611f50565b34801561060957600080fd5b5061053d61061836600461550e565b612258565b34801561062957600080fd5b506103bc61063836600461555d565b612312565b34801561064957600080fd5b506103bc61065836600461535e565b612474565b34801561066957600080fd5b5060035461053d9060ff1681565b34801561068357600080fd5b506103bc610692366004615578565b6124de565b3480156106a357600080fd5b50600054600160a01b900460ff1661053d565b3480156106c257600080fd5b506103bc6106d1366004615379565b612980565b3480156106e257600080fd5b5061044f60045481565b3480156106f857600080fd5b506103bc61070736600461566b565b612b99565b34801561071857600080fd5b506103bc61072736600461535e565b612bfc565b34801561073857600080fd5b506103bc61074736600461535e565b612c66565b34801561075857600080fd5b506104a261076736600461535e565b6009602052600090815260409020546001600160a01b031681565b34801561078e57600080fd5b50600d546104a2906001600160a01b031681565b3480156107ae57600080fd5b506103bc612cb7565b3480156107c357600080fd5b506103bc612cc0565b3480156107d857600080fd5b506103bc6107e736600461535e565b612d12565b3480156107f857600080fd5b506103bc61080736600461535e565b612e5a565b34801561081857600080fd5b5061053d61082736600461535e565b60016020526000908152604090205460ff1681565b34801561084857600080fd5b506103bc61308c565b34801561085d57600080fd5b506103bc61086c36600461535e565b613123565b34801561087d57600080fd5b5061044f600e5481565b34801561089357600080fd5b5061044f60055481565b3480156108a957600080fd5b506103bc613174565b3480156108be57600080fd5b506103bc6108cd366004615309565b6131db565b3480156108de57600080fd5b5060075461044f565b3480156108f357600080fd5b5061053d6109023660046157af565b6132d9565b34801561091357600080fd5b506000546001600160a01b03166104a2565b34801561093157600080fd5b5061053d610940366004615379565b600a6020526000908152604090205460ff1681565b34801561096157600080fd5b506103bc610970366004615827565b6134bd565b34801561098157600080fd5b506104a2610990366004615379565b61358b565b3480156109a157600080fd5b506104a27f0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c66781565b3480156109d557600080fd5b5061053d6109e436600461535e565b60026020526000908152604090205460ff1681565b348015610a0557600080fd5b50610a32610a1436600461535e565b6001600160a01b031660009081526008602052604090205460ff1690565b60405161045991906158e0565b348015610a4b57600080fd5b506104a2610a5a366004615379565b6135b5565b348015610a6b57600080fd5b5061053d610a7a36600461535e565b6135c5565b348015610a8b57600080fd5b5061044f610a9a36600461535e565b6001600160a01b031660009081526008602052604090206001015490565b348015610ac457600080fd5b506103bc610ad3366004615309565b6135fd565b348015610ae457600080fd5b506103bc610af33660046158ee565b6136f5565b348015610b0457600080fd5b5061044f610b133660046154f3565b600b6020526000908152604090205481565b348015610b3157600080fd5b50610b45610b4036600461590a565b6137f8565b604051610459919061593d565b348015610b5e57600080fd5b506103bc610b6d36600461535e565b613af1565b348015610b7e57600080fd5b50610bfa610b8d36600461535e565b600860205260009081526040902080546001820154600283015460038401546004850154600686015460079096015460ff8616966101009096046001600160a01b0316959067ffffffffffffffff80821691680100000000000000008104821691600160801b909104168a565b6040516104599a999897969594939291906159dc565b600054600160a01b900460ff1615610c625760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064015b60405180910390fd5b33670de0b6b3a7640000821015610cbb5760405162461bcd60e51b815260206004820152601860248201527f4d696e696d616c20616d6f756e7420697320312043454c5200000000000000006044820152606401610c59565b6001600160a01b038316600090815260086020526040812090815460ff166003811115610cea57610cea6158a8565b1415610d385760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b6000610d4d8483600101548460020154613bbe565b6001600160a01b0384166000908152600584016020526040812080549293509183918391610d7c908490615a5e565b9250508190555081836002016000828254610d979190615a5e565b9250508190555084836001016000828254610db29190615a5e565b9091555060039050835460ff166003811115610dd057610dd06158a8565b1415610dfb578460046000828254610de89190615a5e565b90915550506001830154610dfb90613beb565b610e306001600160a01b037f0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c66716853088613d0e565b6001830154815460408051928352602083019190915281018690526001600160a01b0380861691908816907f2e289e5a72f8e92e344eb866e0a32621f332835d2df2cf1f76e5a345b23cf1ea9060600160405180910390a3505050505050565b6000546001600160a01b03163314610ed85760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6003805460ff1916911515919091179055565b6000546001600160a01b03163314610f335760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6001600160a01b03811660009081526002602052604090205460ff1615610f9c5760405162461bcd60e51b815260206004820152601360248201527f416c72656164792077686974656c6973746564000000000000000000000000006044820152606401610c59565b6001600160a01b038116600081815260026020908152604091829020805460ff1916600117905590519182527fee1504a83b6d4a361f4c1dc78ab59bfa30d6a3b6612c403e86bb01ef2984295f91015b60405180910390a150565b600054600160a01b900460ff166110505760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c59565b6000546001600160a01b031633146110985760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6110cc6001600160a01b037f0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c667163383613da6565b50565b6000546001600160a01b031633146111175760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6008600052600b6020527f71f482bdabd1ea844d62c952b094e632959690d7448ca2aab34034ec9856935855565b6000546001600160a01b0316331461118d5760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6001600160a01b03811660009081526002602052604090205460ff166111f55760405162461bcd60e51b815260206004820152600f60248201527f4e6f742077686974656c697374656400000000000000000000000000000000006044820152606401610c59565b6001600160a01b038116600081815260026020908152604091829020805460ff1916905590519182527f270d9b30cf5b0793bbfd54c9d5b94aeb49462b8148399000265144a8722da6b69101610fec565b336000818152600960205260409020546001600160a01b03161561127f5750336000908152600960205260409020546001600160a01b03165b6001600160a01b03811660009081526008602052604090206001815460ff1660038111156112af576112af6158a8565b14806112d057506002815460ff1660038111156112ce576112ce6158a8565b145b61131c5760405162461bcd60e51b815260206004820152601860248201527f496e76616c69642076616c696461746f722073746174757300000000000000006044820152606401610c59565b600781015467ffffffffffffffff1643101561137a5760405162461bcd60e51b815260206004820152601660248201527f426f6e6420626c6f636b206e6f742072656163686564000000000000000000006044820152606401610c59565b6005544310156113cc5760405162461bcd60e51b815260206004820152601b60248201527f546f6f206672657175656e742076616c696461746f7220626f6e6400000000006044820152606401610c59565b6007600052600b6020527ff5559028dc9ba50d75343c779b2f75e13a84a14662932fc67a486f263ca31a96546114029043615a5e565b600555611410826001612258565b61145c5760405162461bcd60e51b815260206004820152601360248201527f4e6f742068617665206d696e20746f6b656e73000000000000000000000000006044820152606401610c59565b6003600052600b6020527f64c15cc42be7899b001f818cf4433057002112c418d1d3a67cd5cb453051d33e546007548111156114ad5761149b83613dd6565b6114a88260010154613beb565b505050565b6000196000805b83811015611562578260086000600784815481106114d4576114d4615a76565b60009182526020808320909101546001600160a01b03168352820192909252604001902060010154101561155057809150600860006007838154811061151c5761151c615a76565b60009182526020808320909101546001600160a01b0316835282019290925260400190206001015492508261155057611562565b8061155a81615a8c565b9150506114b4565b50818460010154116115b65760405162461bcd60e51b815260206004820152601360248201527f496e73756666696369656e7420746f6b656e73000000000000000000000000006044820152606401610c59565b6115c08582613e2a565b6115cd8460010154613beb565b5050505050565b6000600360045460026115e79190615aa7565b6115f19190615ac6565b6115fc906001615a5e565b905090565b600054600160a01b900460ff161561164e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c59565b600046306040516020016116a492919091825260601b6bffffffffffffffffffffffff191660208201527f536c617368000000000000000000000000000000000000000000000000000000603482015260390190565b6040516020818303038152906040528051906020012090506116ee8186866040516020016116d493929190615ae8565b60408051601f198184030181529190526109028486615b02565b50600061173086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613ea592505050565b9050806060015167ffffffffffffffff16421061178f5760405162461bcd60e51b815260206004820152600d60248201527f536c6173682065787069726564000000000000000000000000000000000000006044820152606401610c59565b620f4240816040015167ffffffffffffffff1611156117f05760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420736c61736820666163746f720000000000000000000000006044820152606401610c59565b6008600052600b6020527f71f482bdabd1ea844d62c952b094e632959690d7448ca2aab34034ec9856935854604082015167ffffffffffffffff1611156118795760405162461bcd60e51b815260206004820152601760248201527f457863656564206d617820736c61736820666163746f720000000000000000006044820152606401610c59565b60208082015167ffffffffffffffff166000908152600a909152604090205460ff16156118e85760405162461bcd60e51b815260206004820152601060248201527f5573656420736c617368206e6f6e6365000000000000000000000000000000006044820152606401610c59565b60208082015167ffffffffffffffff166000908152600a82526040808220805460ff1916600117905583516001600160a01b0381168352600890935290206003815460ff16600381111561193e5761193e6158a8565b148061195f57506002815460ff16600381111561195d5761195d6158a8565b145b6119ab5760405162461bcd60e51b815260206004820152601860248201527f496e76616c69642076616c696461746f722073746174757300000000000000006044820152606401610c59565b6000620f4240846040015167ffffffffffffffff1683600101546119cf9190615aa7565b6119d99190615ac6565b9050808260010160008282546119ef9190615b0f565b9091555060039050825460ff166003811115611a0d57611a0d6158a8565b1415611a5c578060046000828254611a259190615b0f565b9091555050608084015167ffffffffffffffff16151580611a4e5750611a4c836001612258565b155b15611a5c57611a5c83614117565b6002825460ff166003811115611a7457611a746158a8565b148015611a8f57506000846080015167ffffffffffffffff16115b15611ad2576080840151611aad9067ffffffffffffffff1643615a5e565b60078301805467ffffffffffffffff191667ffffffffffffffff929092169190911790555b60006001600160a01b0316836001600160a01b03167f2e289e5a72f8e92e344eb866e0a32621f332835d2df2cf1f76e5a345b23cf1ea8460010154600085611b1990615b26565b6040805193845260208401929092529082015260600160405180910390a36000620f4240856040015167ffffffffffffffff168460030154611b5b9190615aa7565b611b659190615ac6565b905080836003016000828254611b7b9190615b0f565b90915550611b8b90508183615a5e565b91506000805b8660a0015151811015611d255760008760a001518281518110611bb657611bb6615a76565b6020026020010151905084816020015184611bd19190615a5e565b1115611be757611be18386615b0f565b60208201525b602081015115611d12576020810151611c009084615a5e565b81519093506001600160a01b0316611c8b576020810151611c4d906001600160a01b037f0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c66716903390613da6565b60208082015160405190815233917fb1375221b23a15d2f6887c7dbdc6745a07d9a5245076d51fb41879590ebbd2a3910160405180910390a2611d12565b80516020820151611cc6916001600160a01b037f0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c6671691613da6565b80600001516001600160a01b03167fb1375221b23a15d2f6887c7dbdc6745a07d9a5245076d51fb41879590ebbd2a38260200151604051611d0991815260200190565b60405180910390a25b5080611d1d81615a8c565b915050611b91565b50611d308184615b0f565b600e6000828254611d419190615a5e565b90915550506020808701516040805167ffffffffffffffff90921682529181018590526001600160a01b038716917f10863f35bc5db9fda133333468bf7b1ceaaa88cb4263c061f890f97b79bf9008910160405180910390a25050505050505050505050565b3360009081526001602052604090205460ff16611e065760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610c59565b611e0e61427d565b565b60075460609060009067ffffffffffffffff811115611e3157611e316155b4565b604051908082528060200260200182016040528015611e7657816020015b6040805180820190915260008082526020820152815260200190600190039081611e4f5790505b50905060005b600754811015611f0b57600060078281548110611e9b57611e9b615a76565b60009182526020808320909101546040805180820182526001600160a01b039092168083528085526008845293206001015491810191909152845191925090849084908110611eec57611eec615a76565b6020026020010181905250508080611f0390615a8c565b915050611e7c565b50919050565b6000600b6000836008811115611f2957611f296158a8565b6008811115611f3a57611f3a6158a8565b8152602001908152602001600020549050919050565b6001600160a01b03811660009081526008602052604081203391815460ff166003811115611f8057611f806158a8565b1415611fce5760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b6001600160a01b03821660009081526005820160209081526040822060028352600b9091527fa50eece07c7db1631545c0069bd8f5f54d5935e215d59097edf258a44ba916345483549192909160019060ff166003811115612032576120326158a8565b60028501549114915063ffffffff1660005b600285015463ffffffff640100000000909104811690831610156120f6578280612094575063ffffffff821660009081526001808701602052604090912001544390612091908690615a5e565b11155b156120df5763ffffffff821660009081526001860160205260409020546120bb9082615a5e565b63ffffffff83166000908152600180880160205260408220828155015590506120e4565b6120f6565b816120ee81615b43565b925050612044565b60028501805463ffffffff191663ffffffff8416179055806121805760405162461bcd60e51b815260206004820152602560248201527f4e6f20756e64656c65676174696f6e20726561647920746f20626520636f6d7060448201527f6c657465640000000000000000000000000000000000000000000000000000006064820152608401610c59565b60006121958288600301548960040154614323565b9050818760040160008282546121ab9190615b0f565b92505081905550808760030160008282546121c69190615b0f565b9091555061220090506001600160a01b037f0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c667168983613da6565b876001600160a01b0316896001600160a01b03167f4d10bd049775c77bd7f255195afba5088028ecb3c7c277d393ccff7934f2f92c8360405161224591815260200190565b60405180910390a3505050505050505050565b6001600160a01b03821660009081526008602090815260408220600181015460048452600b9092527f12d0c11577e2f0950f57c455c117796550b79f444811db8ba2f69c57b646c784549091908110156122b75760009250505061230c565b8315612305576001600160a01b038516600090815260058301602052604081205460028401546122e991908490614323565b90508260060154811015612303576000935050505061230c565b505b6001925050505b92915050565b33600081815260086020526040812090815460ff166003811115612338576123386158a8565b14156123865760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b6127108367ffffffffffffffff1611156123e25760405162461bcd60e51b815260206004820152601060248201527f496e76616c6964206e65772072617465000000000000000000000000000000006044820152606401610c59565b60078101805467ffffffffffffffff60801b1916600160801b67ffffffffffffffff8616908102919091179091556040805160208101929092526001600160a01b038416917f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c910160408051601f198184030181529082905261246791600090615bbf565b60405180910390a2505050565b6000546001600160a01b031633146124bc5760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b600054600160a01b900460ff161561252b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c59565b60035460ff1615612595573360009081526002602052604090205460ff166125955760405162461bcd60e51b815260206004820152601960248201527f43616c6c6572206973206e6f742077686974656c6973746564000000000000006044820152606401610c59565b33600081815260086020526040812090815460ff1660038111156125bb576125bb6158a8565b146126085760405162461bcd60e51b815260206004820152601860248201527f56616c696461746f7220697320696e697469616c697a656400000000000000006044820152606401610c59565b6001600160a01b03851660009081526008602052604081205460ff166003811115612635576126356158a8565b146126825760405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206f746865722076616c696461746f72000000000000006044820152606401610c59565b6001600160a01b0382811660009081526009602052604090205416156126ea5760405162461bcd60e51b815260206004820152601960248201527f56616c696461746f72206973206f74686572207369676e6572000000000000006044820152606401610c59565b6001600160a01b0385811660009081526009602052604090205416156127525760405162461bcd60e51b815260206004820152601360248201527f5369676e657220616c72656164792075736564000000000000000000000000006044820152606401610c59565b6127108367ffffffffffffffff1611156127ae5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420636f6d6d697373696f6e20726174650000000000000000006044820152606401610c59565b6005600052600b6020527febae6141bae5521e99e0a8d610356b0f501fea54980b59c84841db43ba7204f4548410156128295760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e74206d696e2073656c662064656c65676174696f6e6044820152606401610c59565b80547fffffffffffffffffffffff0000000000000000000000000000000000000000001660ff196101006001600160a01b03888116918202929092169290921760019081178455600680850188905560078501805467ffffffffffffffff60801b1916600160801b67ffffffffffffffff8a1602179055805491820190557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0180546001600160a01b031990811692861692831790915560009283526009602052604090922080549092161790556129018285610c10565b604080516001600160a01b03878116602083015291810186905267ffffffffffffffff85166060820152908316907f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c9060800160408051601f198184030181529082905261297191600090615c1e565b60405180910390a25050505050565b33600081815260086020526040812090815460ff1660038111156129a6576129a66158a8565b14156129f45760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b6005600052600b6020527febae6141bae5521e99e0a8d610356b0f501fea54980b59c84841db43ba7204f454831015612a6f5760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e74206d696e2073656c662064656c65676174696f6e6044820152606401610c59565b8060060154831015612b3c576003815460ff166003811115612a9357612a936158a8565b1415612ae15760405162461bcd60e51b815260206004820152601360248201527f56616c696461746f7220697320626f6e646564000000000000000000000000006044820152606401610c59565b6006600052600b6020527f0387e9d1203691d8e3362a7e4c6723de358a4010d7f31ecbec3fbfc61d1c75fc54612b179043615a5e565b60078201805467ffffffffffffffff191667ffffffffffffffff929092169190911790555b6006810183905560408051602081018590526001600160a01b038416917f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c910160408051601f198184030181529082905261246791600090615c4c565b612ba7876109028789615b02565b612bf35760405162461bcd60e51b815260206004820152601560248201527f4661696c656420746f20766572696679207369677300000000000000000000006044820152606401610c59565b50505050505050565b6000546001600160a01b03163314612c445760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314612cae5760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6110cc8161433c565b611e0e3361433c565b6000546001600160a01b03163314612d085760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b611e0e60006143f5565b6001600160a01b03811660009081526008602052604090206002815460ff166003811115612d4257612d426158a8565b14612d8f5760405162461bcd60e51b815260206004820152601760248201527f56616c696461746f72206e6f7420756e626f6e64696e670000000000000000006044820152606401610c59565b600781015468010000000000000000900467ffffffffffffffff16431015612df95760405162461bcd60e51b815260206004820152601860248201527f556e626f6e6420626c6f636b206e6f74207265616368656400000000000000006044820152606401610c59565b805460ff1916600190811782556007820180546fffffffffffffffff0000000000000000191690555b6040516001600160a01b038416907fd5e59fa85493a77fb57f6bf9080f2f71fde9de0eadc62b27b43b6263f3f1f59a90600090a35050565b33600081815260086020526040812090815460ff166003811115612e8057612e806158a8565b1415612ece5760405162461bcd60e51b815260206004820152601960248201527f56616c696461746f72206e6f7420696e697469616c697a6564000000000000006044820152606401610c59565b6001600160a01b038381166000908152600960205260409020541615612f365760405162461bcd60e51b815260206004820152601360248201527f5369676e657220616c72656164792075736564000000000000000000000000006044820152606401610c59565b816001600160a01b0316836001600160a01b031614612fc9576001600160a01b03831660009081526008602052604081205460ff166003811115612f7c57612f7c6158a8565b14612fc95760405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206f746865722076616c696461746f72000000000000006044820152606401610c59565b8054610100908190046001600160a01b03908116600090815260096020908152604080832080546001600160a01b031990811690915586547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1689861696870217875585845292819020805490931693871693841790925581519081019390935290917f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c910160408051601f198184030181529082905261246791600090615c93565b6000600e54116130de5760405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f20636f6c6c65637400000000000000000000000000006044820152606401610c59565b600d54600e5461311c916001600160a01b037f0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c667811692911690613da6565b6000600e55565b6000546001600160a01b0316331461316b5760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6110cc81614445565b3360009081526001602052604090205460ff166131d35760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610c59565b611e0e614503565b670de0b6b3a76400008110156132335760405162461bcd60e51b815260206004820152601960248201527f4d696e696d616c20616d6f756e742069732031207368617265000000000000006044820152606401610c59565b6001600160a01b038216600090815260086020526040812090815460ff166003811115613262576132626158a8565b14156132b05760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b60006132c58383600101548460020154614323565b90506132d38285838661458b565b50505050565b60008061333a84805190602001206040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050600080806133486115d4565b905060005b865181101561347457600061338488838151811061336d5761336d615a76565b60200260200101518761492e90919063ffffffff16565b9050836001600160a01b0316816001600160a01b0316116133e75760405162461bcd60e51b815260206004820152601e60248201527f5369676e657273206e6f7420696e20617363656e64696e67206f7264657200006044820152606401610c59565b6001600160a01b038082166000908152600960209081526040808320549093168252600890522090935083906003815460ff16600381111561342b5761342b6158a8565b14613437575050613462565b60018101546134469087615a5e565b955083861061345f57600197505050505050505061230c565b50505b8061346c81615a8c565b91505061334d565b5060405162461bcd60e51b815260206004820152601260248201527f51756f72756d206e6f74207265616368656400000000000000000000000000006044820152606401610c59565b6001600160a01b038516600090815260086020526040812090815460ff1660038111156134ec576134ec6158a8565b141561353a5760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b856001600160a01b03167f3683b59f352bc42833c21c736ba7631d3e35fed49723ebac8298d4e0f36e512c868686863360405161357b959493929190615d03565b60405180910390a2505050505050565b6006818154811061359b57600080fd5b6000918252602090912001546001600160a01b0316905081565b6007818154811061359b57600080fd5b600060036001600160a01b03831660009081526008602052604090205460ff1660038111156135f6576135f66158a8565b1492915050565b670de0b6b3a76400008110156136555760405162461bcd60e51b815260206004820152601860248201527f4d696e696d616c20616d6f756e7420697320312043454c5200000000000000006044820152606401610c59565b6001600160a01b038216600090815260086020526040812090815460ff166003811115613684576136846158a8565b14156136d25760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f72206973206e6f7420696e697469616c697a6564000000006044820152606401610c59565b60006136e78383600101548460020154613bbe565b90506132d38285858461458b565b600c546001600160a01b0316331461374f5760405162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f7420676f7620636f6e74726163740000000000006044820152606401610c59565b6003826008811115613763576137636158a8565b14156137bb576007548110156137bb5760405162461bcd60e51b815260206004820152600d60248201527f696e76616c69642076616c7565000000000000000000000000000000000000006044820152606401610c59565b80600b60008460088111156137d2576137d26158a8565b60088111156137e3576137e36158a8565b81526020810191909152604001600020555050565b61383a6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016060815260200160008152602001600081525090565b6001600160a01b038084166000908152600860209081526040808320938616835260058401909152812080546001840154600285015492939261387e929190614323565b60026000908152600b6020527fa50eece07c7db1631545c0069bd8f5f54d5935e215d59097edf258a44ba916345485549293509091829190829060019060ff1660038111156138cf576138cf6158a8565b6002880154911491506000906138f69063ffffffff80821691640100000000900416615d46565b63ffffffff16905060008167ffffffffffffffff811115613919576139196155b4565b60405190808252806020026020018201604052801561395e57816020015b60408051808201909152600080825260208201528152602001906001900390816139375790505b50905060005b82811015613a7557600289015460018a01906000906139899063ffffffff1684615a5e565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250508282815181106139c8576139c8615a76565b60200260200101819052508181815181106139e5576139e5615a76565b602002602001015160000151876139fc9190615a5e565b96508380613a3257504385838381518110613a1957613a19615a76565b602002602001015160200151613a2f9190615a5e565b11155b15613a6357818181518110613a4957613a49615a76565b60200260200101516000015186613a609190615a5e565b95505b80613a6d81615a8c565b915050613964565b506000613a8b878b600301548c60040154614323565b90506000613aa2878c600301548d60040154614323565b90506040518060c001604052808f6001600160a01b031681526020018a81526020018b600001548152602001848152602001838152602001828152509b50505050505050505050505092915050565b6000546001600160a01b03163314613b395760405162461bcd60e51b81526020600482018190526024820152600080516020615dce8339815191526044820152606401610c59565b6001600160a01b038116613bb55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610c59565b6110cc816143f5565b600082613bcc575082613be4565b82613bd78386615aa7565b613be19190615ac6565b90505b9392505050565b6007546002811480613bfd5750806003145b15613c8257613c0a6115d4565b8210613c7e5760405162461bcd60e51b815260206004820152602e60248201527f53696e676c652076616c696461746f722073686f756c64206e6f74206861766560448201527f2071756f72756d20746f6b656e730000000000000000000000000000000000006064820152608401610c59565b5050565b6003811115613c7e576003600454613c9a9190615ac6565b8210613c7e5760405162461bcd60e51b815260206004820152602b60248201527f53696e676c652076616c696461746f722073686f756c64206e6f74206861766560448201527f20312f3320746f6b656e730000000000000000000000000000000000000000006064820152608401610c59565b6040516001600160a01b03808516602483015283166044820152606481018290526132d39085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526149d2565b6040516001600160a01b0383166024820152604481018290526114a890849063a9059cbb60e01b90606401613d42565b600780546001810182556000919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319166001600160a01b0383161790556110cc81614ab7565b613e5a60078281548110613e4057613e40615a76565b6000918252602090912001546001600160a01b0316614b1d565b8160078281548110613e6e57613e6e615a76565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550613c7e82614ab7565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a084015283518085019094528184528301849052909190613ef4826006614bc4565b905080600681518110613f0957613f09615a76565b602002602001015167ffffffffffffffff811115613f2957613f296155b4565b604051908082528060200260200182016040528015613f6e57816020015b6040805180820190915260008082526020820152815260200190600190039081613f475790505b508360a00181905250600081600681518110613f8c57613f8c615a76565b6020026020010181815250506000805b6020840151518451101561410e57613fb384614c7e565b90925090508160011415613fe257613fd2613fcd85614cb8565b614d75565b6001600160a01b03168552613f9c565b816002141561400857613ff484614d80565b67ffffffffffffffff166020860152613f9c565b816003141561402e5761401a84614d80565b67ffffffffffffffff166040860152613f9c565b81600414156140545761404084614d80565b67ffffffffffffffff166060860152613f9c565b816005141561407a5761406684614d80565b67ffffffffffffffff166080860152613f9c565b81600614156140ff5761409461408f85614cb8565b614e02565b8560a00151846006815181106140ac576140ac615a76565b6020026020010151815181106140c4576140c4615a76565b6020026020010181905250826006815181106140e2576140e2615a76565b6020026020010180518091906140f790615a8c565b905250613f9c565b6141098482614ea9565b613f9c565b50505050919050565b60075460009061412990600190615b0f565b905060005b60075481101561423457826001600160a01b03166007828154811061415557614155615a76565b6000918252602090912001546001600160a01b0316141561422257818110156141e6576007828154811061418b5761418b615a76565b600091825260209091200154600780546001600160a01b0390921691839081106141b7576141b7615a76565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b60078054806141f7576141f7615d6b565b600082815260209020810160001990810180546001600160a01b03191690550190556114a883614b1d565b8061422c81615a8c565b91505061412e565b5060405162461bcd60e51b815260206004820152601460248201527f4e6f7420626f6e6465642076616c696461746f720000000000000000000000006044820152606401610c59565b600054600160a01b900460ff166142d65760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c59565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600081614331575082613be4565b81613bd78486615aa7565b6001600160a01b03811660009081526001602052604090205460ff166143a45760405162461bcd60e51b815260206004820152601560248201527f4163636f756e74206973206e6f742070617573657200000000000000000000006044820152606401610c59565b6001600160a01b038116600081815260016020908152604091829020805460ff1916905590519182527fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e9101610fec565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526001602052604090205460ff16156144ae5760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c726561647920706175736572000000000000006044820152606401610c59565b6001600160a01b038116600081815260016020818152604092839020805460ff191690921790915590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f89101610fec565b600054600160a01b900460ff16156145505760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c59565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586143063390565b33600081815260058601602052604081208054909184918391906145b0908490615b0f565b92505081905550828660020160008282546145cb9190615b0f565b92505081905550838660010160008282546145e69190615b0f565b9091555050600286015460018701541480159061460557508054600210155b1561462a578054600287018054600090614620908490615b0f565b9091555050600081555b8054158061464157508054670de0b6b3a764000011155b61468d5760405162461bcd60e51b815260206004820152601b60248201527f6e6f7420656e6f7567682072656d61696e696e672073686172657300000000006044820152606401610c59565b6001865460ff1660038111156146a5576146a56158a8565b1415614733576146df6001600160a01b037f0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c667168386613da6565b816001600160a01b0316856001600160a01b03167f4d10bd049775c77bd7f255195afba5088028ecb3c7c277d393ccff7934f2f92c8660405161472491815260200190565b60405180910390a350506132d3565b6003865460ff16600381111561474b5761474b6158a8565b14156147955783600460008282546147639190615b0f565b9250508190555061478885866001600160a01b0316846001600160a01b031614612258565b6147955761479585614117565b6002810154600a906147b89063ffffffff80821691640100000000900416615d46565b63ffffffff161061480b5760405162461bcd60e51b815260206004820152601f60248201527f457863656564206d617820756e64656c65676174696f6e20656e7472696573006044820152606401610c59565b60006148208588600301548960040154613bbe565b9050808760040160008282546148369190615a5e565b92505081905550848760030160008282546148519190615a5e565b909155505060028201805463ffffffff6401000000009182900481166000908152600180870160205260409091208581554391810191909155835490939290041690600461489e83615b43565b91906101000a81548163ffffffff021916908363ffffffff16021790555050836001600160a01b0316876001600160a01b03167f2e289e5a72f8e92e344eb866e0a32621f332835d2df2cf1f76e5a345b23cf1ea8a6001015486600001548a61490690615b26565b6040805193845260208401929092529082015260600160405180910390a35050505050505050565b60008151604114156149625760208201516040830151606084015160001a61495886828585614f1b565b935050505061230c565b81516040141561498a57602082015160408301516149818583836150c4565b9250505061230c565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c59565b6000614a27826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166151079092919063ffffffff16565b8051909150156114a85780806020019051810190614a459190615d81565b6114a85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610c59565b6001600160a01b0381166000908152600860205260408120805460ff191660031781556007810180546fffffffffffffffff00000000000000001916905560018101546004805492939192909190614b10908490615a5e565b9091555060039050612e22565b6001600160a01b03811660009081526008602090815260408220805460ff191660029081178255909252600b90527fa50eece07c7db1631545c0069bd8f5f54d5935e215d59097edf258a44ba9163454614b779043615a5e565b8160070160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550806001015460046000828254614bb79190615b0f565b9091555060029050612e22565b8151606090614bd4836001615a5e565b67ffffffffffffffff811115614bec57614bec6155b4565b604051908082528060200260200182016040528015614c15578160200160208202803683370190505b5091506000805b60208601515186511015614c7557614c3386614c7e565b80925081935050506001848381518110614c4f57614c4f615a76565b60200260200101818151614c639190615a5e565b905250614c708682614ea9565b614c1c565b50509092525090565b6000806000614c8c84614d80565b9050614c99600882615ac6565b9250806007166005811115614cb057614cb06158a8565b915050915091565b60606000614cc583614d80565b90506000818460000151614cd99190615a5e565b9050836020015151811115614ced57600080fd5b8167ffffffffffffffff811115614d0657614d066155b4565b6040519080825280601f01601f191660200182016040528015614d30576020820181803683370190505b50602080860151865192955091818601919083010160005b85811015614d6a578181015183820152614d63602082615a5e565b9050614d48565b505050935250919050565b600061230c82615116565b602080820151825181019091015160009182805b600a811015614dfc5783811a9150614dad816007615aa7565b82607f16901b851794508160801660001415614dea57614dce816001615a5e565b86518790614ddd908390615a5e565b9052509395945050505050565b80614df481615a8c565b915050614d94565b50600080fd5b6040805180820182526000808252602080830182905283518085019094528184528301849052909190805b60208301515183511015614ea157614e4483614c7e565b90925090508160011415614e6e57614e5e613fcd84614cb8565b6001600160a01b03168452614e2d565b8160021415614e9257614e88614e8384614cb8565b61513e565b6020850152614e2d565b614e9c8382614ea9565b614e2d565b505050919050565b6000816005811115614ebd57614ebd6158a8565b1415614ecc576114a882614d80565b6002816005811115614ee057614ee06158a8565b1415610397576000614ef183614d80565b90508083600001818151614f059190615a5e565b905250602083015151835111156114a857600080fd5b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115614f985760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c59565b8360ff16601b1480614fad57508360ff16601c145b6150045760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610c59565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015615058573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166150bb5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c59565b95945050505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821660ff83901c601b016150fd86828785614f1b565b9695505050505050565b6060613be18484600085615175565b6000815160141461512657600080fd5b50602001516c01000000000000000000000000900490565b600060208251111561514f57600080fd5b60208201519050815160206151649190615b0f565b61516f906008615aa7565b1c919050565b6060824710156151ed5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610c59565b843b61523b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c59565b600080866001600160a01b031685876040516152579190615d9e565b60006040518083038185875af1925050503d8060008114615294576040519150601f19603f3d011682016040523d82523d6000602084013e615299565b606091505b50915091506152a98282866152b4565b979650505050505050565b606083156152c3575081613be4565b8251156152d35782518084602001fd5b8160405162461bcd60e51b8152600401610c599190615dba565b80356001600160a01b038116811461530457600080fd5b919050565b6000806040838503121561531c57600080fd5b615325836152ed565b946020939093013593505050565b80151581146110cc57600080fd5b60006020828403121561535357600080fd5b8135613be481615333565b60006020828403121561537057600080fd5b613be4826152ed565b60006020828403121561538b57600080fd5b5035919050565b60008083601f8401126153a457600080fd5b50813567ffffffffffffffff8111156153bc57600080fd5b6020830191508360208285010111156153d457600080fd5b9250929050565b60008083601f8401126153ed57600080fd5b50813567ffffffffffffffff81111561540557600080fd5b6020830191508360208260051b85010111156153d457600080fd5b6000806000806040858703121561543657600080fd5b843567ffffffffffffffff8082111561544e57600080fd5b61545a88838901615392565b9096509450602087013591508082111561547357600080fd5b50615480878288016153db565b95989497509550505050565b602080825282518282018190526000919060409081850190868401855b828110156154d757815180516001600160a01b031685528601518685015292840192908501906001016154a9565b5091979650505050505050565b80356009811061530457600080fd5b60006020828403121561550557600080fd5b613be4826154e4565b6000806040838503121561552157600080fd5b61552a836152ed565b9150602083013561553a81615333565b809150509250929050565b803567ffffffffffffffff8116811461530457600080fd5b60006020828403121561556f57600080fd5b613be482615545565b60008060006060848603121561558d57600080fd5b615596846152ed565b9250602084013591506155ab60408501615545565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156155f3576155f36155b4565b604052919050565b600082601f83011261560c57600080fd5b813567ffffffffffffffff811115615626576156266155b4565b615639601f8201601f19166020016155ca565b81815284602083860101111561564e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060006080888a03121561568657600080fd5b873567ffffffffffffffff8082111561569e57600080fd5b6156aa8b838c016155fb565b985060208a01359150808211156156c057600080fd5b6156cc8b838c016153db565b909850965060408a01359150808211156156e557600080fd5b6156f18b838c016153db565b909650945060608a013591508082111561570a57600080fd5b506157178a828b016153db565b989b979a50959850939692959293505050565b600067ffffffffffffffff80841115615745576157456155b4565b8360051b60206157568183016155ca565b8681529350908401908084018783111561576f57600080fd5b855b838110156157a3578035858111156157895760008081fd5b6157958a828a016155fb565b835250908201908201615771565b50505050509392505050565b600080604083850312156157c257600080fd5b823567ffffffffffffffff808211156157da57600080fd5b6157e6868387016155fb565b935060208501359150808211156157fc57600080fd5b508301601f8101851361580e57600080fd5b61581d8582356020840161572a565b9150509250929050565b60008060008060006060868803121561583f57600080fd5b615848866152ed565b9450602086013567ffffffffffffffff8082111561586557600080fd5b61587189838a01615392565b9096509450604088013591508082111561588a57600080fd5b5061589788828901615392565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b600481106158dc57634e487b7160e01b600052602160045260246000fd5b9052565b6020810161230c82846158be565b6000806040838503121561590157600080fd5b615325836154e4565b6000806040838503121561591d57600080fd5b615926836152ed565b9150615934602084016152ed565b90509250929050565b6000602080835260e083016001600160a01b038551168285015281850151604081818701528087015160608701526060870151915060c06080870152828251808552610100880191508584019450600093505b808410156159b95784518051835286015186830152938501936001939093019290820190615990565b50608088015160a088015260a088015160c0880152809550505050505092915050565b61014081016159eb828d6158be565b6001600160a01b039a909a16602082015260408101989098526060880196909652608087019490945260a086019290925260c085015267ffffffffffffffff90811660e08501529081166101008401521661012090910152919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115615a7157615a71615a48565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600019821415615aa057615aa0615a48565b5060010190565b6000816000190483118215151615615ac157615ac1615a48565b500290565b600082615ae357634e487b7160e01b600052601260045260246000fd5b500490565b838152818360208301376000910160200190815292915050565b6000613be436848461572a565b600082821015615b2157615b21615a48565b500390565b6000600160ff1b821415615b3c57615b3c615a48565b5060000390565b600063ffffffff80831681811415615b5d57615b5d615a48565b6001019392505050565b60005b83811015615b82578181015183820152602001615b6a565b838111156132d35750506000910152565b60008151808452615bab816020860160208601615b67565b601f01601f19169290920160200192915050565b60608152600a60608201527f636f6d6d697373696f6e00000000000000000000000000000000000000000000608082015260a060208201526000615c0660a0830185615b93565b90506001600160a01b03831660408301529392505050565b6060815260046060820152631a5b9a5d60e21b608082015260a060208201526000615c0660a0830185615b93565b60608152601360608201527f6d696e2d73656c662d64656c65676174696f6e00000000000000000000000000608082015260a060208201526000615c0660a0830185615b93565b60608152600660608201527f7369676e65720000000000000000000000000000000000000000000000000000608082015260a060208201526000615c0660a0830185615b93565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b606081526000615d17606083018789615cda565b8281036020840152615d2a818688615cda565b9150506001600160a01b03831660408301529695505050505050565b600063ffffffff83811690831681811015615d6357615d63615a48565b039392505050565b634e487b7160e01b600052603160045260246000fd5b600060208284031215615d9357600080fd5b8151613be481615333565b60008251615db0818460208701615b67565b9190910192915050565b602081526000613be46020830184615b9356fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a26469706673582212201e41fbe148ca51c46448ba41ffc013bb54a58fc4e688ebf2d9e4fc84d2b1e7d164736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c6670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022600000000000000000000000000000000000000000000000000000000000008a7000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000000000000000019c800000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _celerTokenAddress (address): 0x4F9254C83EB525f9FCf346490bbb3ed28a81C667
Arg [1] : _proposalDeposit (uint256): 0
Arg [2] : _votingPeriod (uint256): 550
Arg [3] : _unbondingPeriod (uint256): 2215
Arg [4] : _maxBondedValidators (uint256): 21
Arg [5] : _minValidatorTokens (uint256): 10000000000000000000000
Arg [6] : _minSelfDelegation (uint256): 10000000000000000000000
Arg [7] : _advanceNoticePeriod (uint256): 6600
Arg [8] : _validatorBondInterval (uint256): 50
Arg [9] : _maxSlashFactor (uint256): 0
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000004f9254c83eb525f9fcf346490bbb3ed28a81c667
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000226
Arg [3] : 00000000000000000000000000000000000000000000000000000000000008a7
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [5] : 00000000000000000000000000000000000000000000021e19e0c9bab2400000
Arg [6] : 00000000000000000000000000000000000000000000021e19e0c9bab2400000
Arg [7] : 00000000000000000000000000000000000000000000000000000000000019c8
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000032
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.