Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
LagrangeCommittee
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "../interfaces/ILagrangeCommittee.sol"; import "../interfaces/ILagrangeService.sol"; import "../interfaces/IVoteWeigher.sol"; import "../library/BLSKeyChecker.sol"; contract LagrangeCommittee is BLSKeyChecker, Initializable, OwnableUpgradeable, ILagrangeCommittee { ILagrangeService public immutable service; IVoteWeigher public immutable voteWeigher; // Leaf Node Prefix bytes1 public constant LEAF_NODE_PREFIX = 0x01; // Inner Node Prefix bytes1 public constant INNER_NODE_PREFIX = 0x02; // Registered ChainIDs uint32[] public chainIDs; // ChainID => Committee mapping(uint32 => CommitteeDef) public committeeParams; // ChainID => Epoch => CommitteeData mapping(uint32 => mapping(uint256 => CommitteeData)) public committees; // ChainID => Operator address[] mapping(uint32 => address[]) public committeeAddrs; // Tree Depth => Node Value mapping(uint8 => bytes32) private zeroHashes; mapping(address => OperatorStatus) public operatorsStatus; // ChainID => Epoch check if committee tree has been updated mapping(uint32 => uint256) public updatedEpoch; mapping(uint32 => mapping(address => bool)) public subscribedChains; modifier onlyService() { require(msg.sender == address(service), "Only Lagrange service can call this function."); _; } constructor(ILagrangeService _service, IVoteWeigher _voteWeigher) { service = _service; voteWeigher = _voteWeigher; _disableInitializers(); } // Initializer: sets owner function initialize(address initialOwner) external initializer { // Initialize zero hashes for (uint8 i = 1; i <= 20; i++) { zeroHashes[i] = _innerHash(zeroHashes[i - 1], zeroHashes[i - 1]); } _transferOwnership(initialOwner); } // Updates the sequencer key, create new one is not exists function updateSequencerBlsPubKey(IBLSKeyChecker.BLSKeyWithProof calldata blsKeyWithProof) external onlyOwner { require(blsKeyWithProof.blsG1PublicKeys.length == 1, "Only one key should be provided."); _validateBLSKeyWithProof(address(this), blsKeyWithProof); operatorsStatus[address(this)].blsPubKeys = blsKeyWithProof.blsG1PublicKeys; if (operatorsStatus[address(this)].blsPubKeys.length == 0) { emit BlsKeyUpdated(address(this), 0, 1, 0); } else { emit BlsKeyUpdated(address(this), 1, 1, 1); } } // Adds a new operator to the committee function addOperator(address operator, address signAddress, BLSKeyWithProof calldata blsKeyWithProof) external onlyService { _validateBlsPubKeys(blsKeyWithProof.blsG1PublicKeys); _registerOperator(operator, signAddress, blsKeyWithProof); } // Removes an operator from the committee function removeOperator(address operator) external onlyService { delete operatorsStatus[operator]; } // Unsubscribe chain by admin function unsubscribeByAdmin(address[] calldata operators, uint32 chainID) external onlyService { uint256 _length = operators.length; for (uint256 i; i < _length; i++) { address _operator = operators[i]; require(subscribedChains[chainID][_operator], "The dedicated chain is not subscribed"); delete subscribedChains[chainID][_operator]; _removeOperatorFromCommitteeAddrs(chainID, _operator); operatorsStatus[_operator].subscribedChainCount--; } } // Adds additional BLS public keys to an operator function addBlsPubKeys(address operator, BLSKeyWithProof calldata blsKeyWithProof) external onlyService { _validateBlsPubKeys(blsKeyWithProof.blsG1PublicKeys); _addBlsPubKeys(operator, blsKeyWithProof); } // Updates an operator's BLS public key for the given index function updateBlsPubKey(address operator, uint32 index, BLSKeyWithProof calldata blsKeyWithProof) external onlyService { _validateBLSKeyWithProof(operator, blsKeyWithProof); require(blsKeyWithProof.blsG1PublicKeys.length == 1, "Length should be 1 for update"); uint256[2][] storage _blsPubKeys = operatorsStatus[operator].blsPubKeys; uint256 _orgLength = _blsPubKeys.length; require(_orgLength > index, "Invalid index"); _checkBlsPubKeyDuplicate(_blsPubKeys, blsKeyWithProof.blsG1PublicKeys[0]); _blsPubKeys[index] = blsKeyWithProof.blsG1PublicKeys[0]; emit BlsKeyUpdated(operator, _orgLength, 1, 1); } // Removes BLS public keys from an operator for the given indices function removeBlsPubKeys(address operator, uint32[] calldata indices) external onlyService { uint256[2][] memory _blsPubKeys = operatorsStatus[operator].blsPubKeys; uint256 _length = _blsPubKeys.length; // it ensures that keep at least one BLS public key require(_length > indices.length, "Invalid indices length, BLS keys cannot be empty."); for (uint256 i; i < indices.length; i++) { require(_length > indices[i], "Invalid index"); _blsPubKeys[indices[i]][0] = 0; _blsPubKeys[indices[i]][1] = 0; } uint32 count; for (uint256 i; i < _length; i++) { if (_blsPubKeys[i][0] != 0 || _blsPubKeys[i][1] != 0) { _blsPubKeys[count] = _blsPubKeys[i]; count++; } } uint256[2][] memory _newBlsPubKeys = new uint256[2][](count); for (uint256 i; i < count; i++) { _newBlsPubKeys[i] = _blsPubKeys[i]; } operatorsStatus[operator].blsPubKeys = _newBlsPubKeys; emit BlsKeyUpdated(operator, _length, 0, indices.length); } // Updates an operator's sign address function updateSignAddress(address operator, address newSignAddress) external onlyService { require(operatorsStatus[operator].blsPubKeys.length != 0, "Operator is not registered."); operatorsStatus[operator].signAddress = newSignAddress; emit SignAddressUpdated(operator, newSignAddress); } function subscribeChain(address operator, uint32 chainID) external onlyService { // Check if the chainID is already registered require(committeeParams[chainID].startBlock > 0, "The dedicated chain is not registered."); (bool locked,) = isLocked(chainID); require(!locked, "The dedicated chain is locked."); UnsubscribedParam[] memory unsubscribedParams = operatorsStatus[operator].unsubscribedParams; uint256 _length = unsubscribedParams.length; for (uint256 i; i < _length; i++) { UnsubscribedParam memory param = unsubscribedParams[i]; if (param.chainID == chainID) { if (param.blockNumber >= block.number) { revert("The dedciated chain is while unsubscribing."); } } } require(!subscribedChains[chainID][operator], "The dedicated chain is already subscribed."); CommitteeDef memory _committeeParam = committeeParams[chainID]; uint96 _voteWeight = voteWeigher.weightOfOperator(_committeeParam.quorumNumber, operator); // voteWeight require(_voteWeight >= _committeeParam.minWeight, "Insufficient Vote Weight"); _subscribeChain(operator, chainID); } function unsubscribeChain(address operator, uint32 chainID) external onlyService { require(subscribedChains[chainID][operator], "The dedicated chain is not subscribed"); (bool locked, uint256 blockNumber) = isLocked(chainID); require(!locked, "The dedicated chain is locked."); _unsubscribeChain(operator, chainID, blockNumber); } // Initializes a new committee, and optionally associates addresses with it. function registerChain( uint32 chainID, uint256 genesisBlock, uint256 epochPeriod, uint256 freezeDuration, uint8 quorumNumber, uint96 minWeight, uint96 maxWeight ) external onlyOwner { require(committeeParams[chainID].startBlock == 0, "Committee has already been initialized."); _validateVotingPowerRange(minWeight, maxWeight); _validateFreezeDuration(epochPeriod, freezeDuration); _initCommittee(chainID, genesisBlock, epochPeriod, freezeDuration, quorumNumber, minWeight, maxWeight); } function updateChain( uint32 chainID, int256 l1Bias, uint256 genesisBlock, uint256 epochPeriod, uint256 freezeDuration, uint8 quorumNumber, uint96 minWeight, uint96 maxWeight ) external onlyOwner { uint256 _startBlock = committeeParams[chainID].startBlock; require(_startBlock != 0, "Chain not initialized"); _validateVotingPowerRange(minWeight, maxWeight); _validateFreezeDuration(epochPeriod, freezeDuration); _updateCommitteeParams( chainID, l1Bias, _startBlock, genesisBlock, epochPeriod, freezeDuration, quorumNumber, minWeight, maxWeight ); } function isUnregisterable(address operator) public view returns (bool, uint256) { OperatorStatus memory _opStatus = operatorsStatus[operator]; if (_opStatus.subscribedChainCount > 0) { return (false, 0); } uint256 _unsubscribeBlockNumber; uint256 _length = _opStatus.unsubscribedParams.length; for (uint256 i; i < _length; i++) { UnsubscribedParam memory param = _opStatus.unsubscribedParams[i]; if (param.blockNumber > _unsubscribeBlockNumber) { _unsubscribeBlockNumber = param.blockNumber; } } return (true, _unsubscribeBlockNumber); } function getBlsPubKeys(address operator) public view returns (uint256[2][] memory) { return operatorsStatus[operator].blsPubKeys; } // Returns chain's committee current and next roots at a given block. function getCommittee(uint32 chainID, uint256 blockNumber) public view returns (CommitteeData memory currentCommittee) { uint256 epochNumber = getEpochNumber(chainID, blockNumber); currentCommittee = committees[chainID][epochNumber]; return currentCommittee; } // Checks if a chain's committee is updatable at a given block function isUpdatable(uint32 chainID, uint256 epochNumber) public view returns (bool) { (, uint256 _freezeBlock,) = getEpochInterval(chainID, epochNumber - 1); return block.number > _freezeBlock; } // Checks if a chain's committee is locked at a given block function isLocked(uint32 chainID) public view returns (bool, uint256) { uint256 _epochNumber = _getEpochNumber(chainID, block.number); (, uint256 _freezeBlock, uint256 _endBlock) = getEpochInterval(chainID, _epochNumber); return (block.number > _freezeBlock, _endBlock); } // If applicable, updates committee based on staking, unstaking, and slashing. function update(uint32 chainID, uint256 epochNumber) external virtual { _updateCommittee(chainID, epochNumber, block.number); } function revertEpoch(uint32 chainID, uint256 epochNumber) public onlyOwner { require(updatedEpoch[chainID] == epochNumber, "The epochNumber is not the latest."); delete committees[chainID][epochNumber]; updatedEpoch[chainID] = epochNumber - 1; } // Computes epoch number for a chain's committee at a given block function getEpochNumber(uint32 chainID, uint256 blockNumber) public view virtual returns (uint256 epochNumber) { epochNumber = _getEpochNumber(chainID, blockNumber); // All the prior blocks belong to epoch 1 if (epochNumber == 0 && blockNumber >= committeeParams[chainID].genesisBlock) epochNumber = 1; } // Get the operator's voting power for the given chainID function getOperatorVotingPower(address opAddr, uint32 chainID) public view returns (uint96) { CommitteeDef memory _committeeParam = committeeParams[chainID]; uint96 _weight = voteWeigher.weightOfOperator(_committeeParam.quorumNumber, opAddr); return _checkVotingPower( uint32(operatorsStatus[opAddr].blsPubKeys.length), _weight, _committeeParam.minWeight, _committeeParam.maxWeight ); } // Get array of voting powers of individual BlsPubKeys function getBlsPubKeyVotingPowers(address opAddr, uint32 chainID) public view returns (uint96[] memory individualVotingPowers) { uint96 _votingPower = getOperatorVotingPower(opAddr, chainID); uint96 _minWeight = committeeParams[chainID].minWeight; uint96 _maxWeight = committeeParams[chainID].maxWeight; return _divideVotingPower(_votingPower, _minWeight, _maxWeight); } function getTokenListForOperator(address operator) external view returns (address[] memory) { uint256 _length = chainIDs.length; uint8[] memory _quorumNumbers = new uint8[](operatorsStatus[operator].subscribedChainCount); uint256 _count; for (uint256 i; i < _length; i++) { uint32 _chainID = chainIDs[i]; if (subscribedChains[_chainID][operator]) { _quorumNumbers[_count++] = committeeParams[_chainID].quorumNumber; } } return voteWeigher.getTokenListForQuorumNumbers(_quorumNumbers); } // Initialize new committee. function _initCommittee( uint32 _chainID, uint256 _genesisBlock, uint256 _duration, uint256 _freezeDuration, uint8 _quorumNumber, uint96 _minWeight, uint96 _maxWeight ) internal { committeeParams[_chainID] = CommitteeDef( block.number, 0, _genesisBlock, _duration, _freezeDuration, _quorumNumber, _minWeight, _maxWeight ); committees[_chainID][0] = CommitteeData(0, 0, 0); chainIDs.push(_chainID); emit InitCommittee(_chainID, _quorumNumber, _genesisBlock, _duration, _freezeDuration, _minWeight, _maxWeight); } // Update committee. function _updateCommitteeParams( uint32 _chainID, int256 _l1Bias, uint256 _startBlock, uint256 _genesisBlock, uint256 _duration, uint256 _freezeDuration, uint8 _quorumNumber, uint96 _minWeight, uint96 _maxWeight ) internal { committeeParams[_chainID] = CommitteeDef( _startBlock, _l1Bias, _genesisBlock, _duration, _freezeDuration, _quorumNumber, _minWeight, _maxWeight ); emit UpdateCommitteeParams( _chainID, _quorumNumber, _l1Bias, _genesisBlock, _duration, _freezeDuration, _minWeight, _maxWeight ); } // Get epoch interval for a given chain function getEpochInterval(uint32 chainID, uint256 epochNumber) public view returns (uint256 startBlock, uint256 freezeBlock, uint256 endBlock) { CommitteeDef memory committeeParam = committeeParams[chainID]; uint256 _lastEpoch = updatedEpoch[chainID]; if (epochNumber == 0) { startBlock = committeeParam.startBlock; endBlock = _lastEpoch == 0 ? committeeParam.startBlock + committeeParam.duration : _getUpdatedBlock(chainID, 1); freezeBlock = endBlock - committeeParam.freezeDuration; return (startBlock, freezeBlock, endBlock); } if (epochNumber <= _lastEpoch) { startBlock = _getUpdatedBlock(chainID, epochNumber); endBlock = _lastEpoch == epochNumber ? startBlock + committeeParam.duration : _getUpdatedBlock(chainID, epochNumber + 1); freezeBlock = endBlock - committeeParam.freezeDuration; } else { uint256 _lastEpochBlock = _lastEpoch > 0 ? _getUpdatedBlock(chainID, _lastEpoch) : committeeParam.startBlock; startBlock = _lastEpochBlock + (epochNumber - _lastEpoch) * committeeParam.duration; endBlock = startBlock + committeeParam.duration; freezeBlock = endBlock - committeeParam.freezeDuration; } } function _getEpochNumber(uint32 _chainID, uint256 _blockNumber) internal view returns (uint256 _epochNumber) { CommitteeDef memory committeeParam = committeeParams[_chainID]; if (_blockNumber < committeeParam.startBlock) { return 0; } uint256 _lastEpoch = updatedEpoch[_chainID]; uint256 _lastEpochBlock = _lastEpoch > 0 ? _getUpdatedBlock(_chainID, _lastEpoch) : committeeParam.startBlock; if (_blockNumber >= _lastEpochBlock) { _epochNumber = _lastEpoch + (_blockNumber - _lastEpochBlock) / committeeParam.duration; } else if (_lastEpoch == 0) { return 0; } else { if (_blockNumber >= _lastEpochBlock - committeeParam.duration) { _epochNumber = _lastEpoch; while (_blockNumber < _getUpdatedBlock(_chainID, _epochNumber)) { _epochNumber--; } return _epochNumber; } // binary search uint256 _low = 0; uint256 _high = _lastEpoch; while (_low < _high - 1) { uint256 _mid = (_low + _high + 1) >> 1; if (_blockNumber < _getUpdatedBlock(_chainID, _mid)) { _high = _mid; } else { _low = _mid + 1; } } _epochNumber = _high - 1; } } function _registerOperator(address _operator, address _signAddress, BLSKeyWithProof memory _blsKeyWithProof) internal { _validateBLSKeyWithProof(_operator, _blsKeyWithProof); delete operatorsStatus[_operator]; OperatorStatus storage _opStatus = operatorsStatus[_operator]; uint256 _orgLength = _opStatus.blsPubKeys.length; _opStatus.signAddress = _signAddress; uint256 _length = _blsKeyWithProof.blsG1PublicKeys.length; for (uint256 i; i < _length; i++) { _checkBlsPubKeyDuplicate(_opStatus.blsPubKeys, _blsKeyWithProof.blsG1PublicKeys[i]); _opStatus.blsPubKeys.push(_blsKeyWithProof.blsG1PublicKeys[i]); } emit BlsKeyUpdated(_operator, _orgLength, _length, 0); } function _addBlsPubKeys(address _operator, BLSKeyWithProof memory _blsKeyWithProof) internal { _validateBLSKeyWithProof(_operator, _blsKeyWithProof); OperatorStatus storage _opStatus = operatorsStatus[_operator]; require(_opStatus.blsPubKeys.length != 0, "Operator is not registered."); uint256 _orgLength = _opStatus.blsPubKeys.length; uint256 _length = _blsKeyWithProof.blsG1PublicKeys.length; for (uint256 i; i < _length; i++) { _checkBlsPubKeyDuplicate(_opStatus.blsPubKeys, _blsKeyWithProof.blsG1PublicKeys[i]); _opStatus.blsPubKeys.push(_blsKeyWithProof.blsG1PublicKeys[i]); } emit BlsKeyUpdated(_operator, _orgLength, _length, 0); } function _checkBlsPubKeyDuplicate(uint256[2][] memory _blsPubKeys, uint256[2] memory _blsPubKey) internal pure { uint256 _length = _blsPubKeys.length; for (uint256 i; i < _length; i++) { require(_blsPubKeys[i][0] != _blsPubKey[0] || _blsPubKeys[i][1] != _blsPubKey[1], "Duplicated BlsPubKey"); } } function _subscribeChain(address _operator, uint32 _chainID) internal { subscribedChains[_chainID][_operator] = true; operatorsStatus[_operator].subscribedChainCount++; committeeAddrs[_chainID].push(_operator); } function _unsubscribeChain(address _operator, uint32 _chainID, uint256 _blockNumber) internal { delete subscribedChains[_chainID][_operator]; OperatorStatus storage _opStatus = operatorsStatus[_operator]; _opStatus.unsubscribedParams.push(UnsubscribedParam(_chainID, _blockNumber)); _opStatus.subscribedChainCount--; _removeOperatorFromCommitteeAddrs(_chainID, _operator); } function _removeOperatorFromCommitteeAddrs(uint32 _chainID, address _operator) internal { uint256 _length = committeeAddrs[_chainID].length; for (uint256 i; i < _length; i++) { if (committeeAddrs[_chainID][i] == _operator) { committeeAddrs[_chainID][i] = committeeAddrs[_chainID][_length - 1]; committeeAddrs[_chainID].pop(); break; } } require(_length == committeeAddrs[_chainID].length + 1, "Operator doesn't exist in committeeAddrs."); } function _updateCommittee(uint32 _chainID, uint256 _epochNumber, uint256 _l1BlockNumber) internal { require(isUpdatable(_chainID, _epochNumber), "Block number is prior to committee freeze window."); require(updatedEpoch[_chainID] + 1 == _epochNumber, "The epochNumber is not sequential."); CommitteeDef memory _committeeParam = committeeParams[_chainID]; uint8 _quorumNumber = _committeeParam.quorumNumber; uint96 _minWeight = _committeeParam.minWeight; uint96 _maxWeight = _committeeParam.maxWeight; address[] memory _operators = committeeAddrs[_chainID]; uint256 _operatorCount = _operators.length; uint256 _leafCounter = 1; // pre-calculate array size (can be bigger than actual size) for (uint256 i; i < _operatorCount;) { unchecked { _leafCounter += operatorsStatus[_operators[i]].blsPubKeys.length; i++; } } bytes32[] memory _committeeLeaves = new bytes32[](_leafCounter); { _leafCounter = 0; if (operatorsStatus[address(this)].blsPubKeys.length != 0) { _committeeLeaves[_leafCounter] = _leafHash(address(this), operatorsStatus[address(this)].blsPubKeys[0], 0); unchecked { _leafCounter++; } } for (uint256 i; i < _operatorCount;) { address _operator = _operators[i]; OperatorStatus storage _opStatus = operatorsStatus[_operator]; uint96 _votingPower = _checkVotingPower( uint32(_opStatus.blsPubKeys.length), // blsPubKeyCount voteWeigher.weightOfOperator(_quorumNumber, _operator), // voteWeight _minWeight, _maxWeight ); uint96 _remained = _votingPower; unchecked { for (uint256 j; _remained > 0;) { uint96 _individualVotingPower; if (_remained >= _maxWeight + _minWeight) { _individualVotingPower = _maxWeight; } else if (_remained > _maxWeight) { _individualVotingPower = _minWeight; } else { _individualVotingPower = _remained; } _remained -= _individualVotingPower; _committeeLeaves[_leafCounter] = _leafHash(_operator, _opStatus.blsPubKeys[j], _individualVotingPower); j++; _leafCounter++; } } unchecked { i++; } } } bytes32 _root; unchecked { // Nothing to overflow/underflow uint256 _childCount = _leafCounter; for (uint8 _h; _childCount > 1; _h++) { uint256 _parentCount = (_childCount + 1) >> 1; for (uint256 _i = 1; _i < _childCount; _i += 2) { _committeeLeaves[_i >> 1] = _innerHash(_committeeLeaves[_i - 1], _committeeLeaves[_i]); } if (_childCount & 1 == 1) { _committeeLeaves[_parentCount - 1] = _innerHash(_committeeLeaves[_childCount - 1], zeroHashes[_h]); } _childCount = _parentCount; } if (_leafCounter > 0) _root = _committeeLeaves[0]; } // Update roots committees[_chainID][_epochNumber].leafCount = uint32(_leafCounter); committees[_chainID][_epochNumber].root = _root; _setUpdatedBlock(_chainID, _epochNumber, _l1BlockNumber); updatedEpoch[_chainID] = _epochNumber; emit UpdateCommittee(_chainID, _epochNumber, _root); } function _getUpdatedBlock(uint32 _chainID, uint256 _epochNumber) internal view virtual returns (uint256) { return committees[_chainID][_epochNumber].updatedBlock; } function _setUpdatedBlock(uint32 _chainID, uint256 _epochNumber, uint256 _l1BlockNumber) internal virtual { committees[_chainID][_epochNumber].updatedBlock = SafeCast.toUint224(_l1BlockNumber); } function _validateBlsPubKeys(uint256[2][] memory _blsPubKeys) internal pure { require(_blsPubKeys.length != 0, "Empty BLS Public Keys."); uint256 _length = _blsPubKeys.length; for (uint256 i; i < _length; i++) { require(_blsPubKeys[i][0] != 0 && _blsPubKeys[i][1] != 0, "Invalid BLS Public Key."); } } // Returns the leaf hash for a given operator function _leafHash(address opAddr, uint256[2] memory blsPubKey, uint96 _votingPower) internal pure returns (bytes32) { return keccak256(abi.encodePacked(LEAF_NODE_PREFIX, blsPubKey[0], blsPubKey[1], opAddr, _votingPower)); } // Calculate the inner node hash from left and right children function _innerHash(bytes32 left, bytes32 right) internal pure returns (bytes32) { return keccak256(abi.encodePacked(INNER_NODE_PREFIX, left, right)); } function _validateVotingPowerRange(uint96 _minWeight, uint96 _maxWeight) internal pure { require(_minWeight > 0 && _maxWeight >= _minWeight * 2, "Invalid min/max Weight"); } function _validateFreezeDuration(uint256 _epochPeriod, uint256 _freezeDuration) internal pure { require(_epochPeriod > _freezeDuration, "Invalid freeze duration"); } function _checkVotingPower(uint32 blsPubKeysCount, uint96 votingPower, uint96 minWeight, uint96 maxWeight) internal pure returns (uint96) { if (votingPower < minWeight) { return 0; } unchecked { uint256 _amountLimit = uint256(maxWeight) * uint256(blsPubKeysCount); // This value can be bigger than type(uint96).max if (votingPower > _amountLimit) { votingPower = uint96(_amountLimit); } } return votingPower; } function _calcActiveBlsPubKeyCount(uint96 _votingPower, uint96 minWeight, uint96 maxWeight) internal pure returns (uint32) { if (_votingPower < minWeight) { return 0; } else { unchecked { uint96 _count = ((_votingPower - 1) / maxWeight) + 1; require(_count <= type(uint32).max, "OverFlow"); return uint32(_count); } } } function _divideVotingPower(uint96 totalWeight, uint96 minWeight, uint96 maxWeight) internal pure returns (uint96[] memory) { uint256 _count = _calcActiveBlsPubKeyCount(totalWeight, minWeight, maxWeight); uint96[] memory _individualVotingPowers = new uint96[](_count); if (_count == 0) return _individualVotingPowers; uint256 _index; uint96 _remained = totalWeight; unchecked { while (_remained >= maxWeight + minWeight) { _individualVotingPowers[_index++] = maxWeight; _remained -= maxWeight; } if (_remained > maxWeight) { _individualVotingPowers[_index++] = minWeight; _individualVotingPowers[_index++] = _remained - minWeight; } else { _individualVotingPowers[_index++] = _remained; } } return _individualVotingPowers; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol) pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248) { require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits"); return int248(value); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240) { require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits"); return int240(value); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232) { require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits"); return int232(value); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224) { require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits"); return int224(value); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216) { require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits"); return int216(value); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208) { require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits"); return int208(value); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200) { require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits"); return int200(value); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192) { require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits"); return int192(value); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184) { require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits"); return int184(value); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176) { require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits"); return int176(value); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168) { require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits"); return int168(value); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160) { require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits"); return int160(value); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152) { require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits"); return int152(value); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144) { require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits"); return int144(value); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136) { require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits"); return int136(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120) { require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits"); return int120(value); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112) { require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits"); return int112(value); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104) { require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits"); return int104(value); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96) { require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits"); return int96(value); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88) { require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits"); return int88(value); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80) { require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits"); return int80(value); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72) { require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits"); return int72(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56) { require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits"); return int56(value); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48) { require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits"); return int48(value); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40) { require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits"); return int40(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24) { require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits"); return int24(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {IBLSKeyChecker} from "./IBLSKeyChecker.sol"; interface ILagrangeCommittee is IBLSKeyChecker { struct UnsubscribedParam { uint32 chainID; uint256 blockNumber; } struct OperatorStatus { address signAddress; uint256[2][] blsPubKeys; uint8 subscribedChainCount; // assume that size of this array is not big UnsubscribedParam[] unsubscribedParams; } struct CommitteeDef { uint256 startBlock; // l1Bias is the difference between the base L1 block number of the given L2 chain and // the maintained L1 block number, for example, if we want to register the Base Mainnet // chain in the Holesky, the l1Bias should be the difference between the Mainnet block // number and the Holesky block number. int256 l1Bias; uint256 genesisBlock; uint256 duration; uint256 freezeDuration; uint8 quorumNumber; uint96 minWeight; uint96 maxWeight; } struct CommitteeData { bytes32 root; uint224 updatedBlock; uint32 leafCount; } function getCommittee(uint32 chainID, uint256 blockNumber) external view returns (CommitteeData memory); // TODO: need to change order of the params for gas optimization function registerChain( uint32 chainID, uint256 genesisBlock, uint256 epochPeriod, uint256 freezeDuration, uint8 quorumNumber, uint96 minWeight, uint96 maxWeight ) external; function updateChain( uint32 chainID, int256 l1Bias, uint256 genesisBlock, uint256 epochPeriod, uint256 freezeDuration, uint8 quorumNumber, uint96 minWeight, uint96 maxWeight ) external; function updateSequencerBlsPubKey(IBLSKeyChecker.BLSKeyWithProof memory blsKeyWithProof) external; function addOperator(address operator, address signAddress, BLSKeyWithProof memory blsKeyWithProof) external; function removeOperator(address operator) external; function unsubscribeByAdmin(address[] memory operators, uint32 chainID) external; function addBlsPubKeys(address operator, BLSKeyWithProof memory blsKeyWithProof) external; function updateBlsPubKey(address operator, uint32 index, BLSKeyWithProof memory blsKeyWithProof) external; function removeBlsPubKeys(address operator, uint32[] memory indices) external; function updateSignAddress(address operator, address newSignAddress) external; function isLocked(uint32 chainID) external view returns (bool, uint256); function subscribeChain(address operator, uint32 chainID) external; function unsubscribeChain(address operator, uint32 chainID) external; function isUnregisterable(address operator) external view returns (bool, uint256); function update(uint32 chainID, uint256 epochNumber) external; function getBlsPubKeys(address operator) external view returns (uint256[2][] memory); function getOperatorVotingPower(address opAddr, uint32 chainID) external view returns (uint96); function getBlsPubKeyVotingPowers(address opAddr, uint32 chainID) external view returns (uint96[] memory); function getTokenListForOperator(address operator) external view returns (address[] memory); // Event fired on initialization of a new committee event InitCommittee( uint256 indexed chainID, uint8 indexed quorumNumber, uint256 genesisBlock, uint256 duration, uint256 freezeDuration, uint96 minWeight, uint96 maxWeight ); // Event fired on updating a committee params event UpdateCommitteeParams( uint256 indexed chainID, uint8 indexed quorumNumber, int256 l1Bias, uint256 genesisBlock, uint256 duration, uint256 freezeDuration, uint96 minWeight, uint96 maxWeight ); // Fired on BlsKeys are added/removed/updated event BlsKeyUpdated(address indexed operator, uint256 orgLength, uint256 added, uint256 removed); // Fired on successful rotation of committee event UpdateCommittee(uint256 indexed chainID, uint256 indexed epochNumber, bytes32 current); // Event fired on updating sign address event SignAddressUpdated(address indexed operator, address indexed signAddress); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol"; import {IBLSKeyChecker} from "./IBLSKeyChecker.sol"; interface ILagrangeService { function addOperatorsToWhitelist(address[] calldata operators) external; function removeOperatorsFromWhitelist(address[] calldata operators) external; function register( address signAddress, IBLSKeyChecker.BLSKeyWithProof memory blsKeyWithProof, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature ) external; function addBlsPubKeys(IBLSKeyChecker.BLSKeyWithProof memory blsKeyWithProof) external; function updateBlsPubKey(uint32 index, IBLSKeyChecker.BLSKeyWithProof memory blsKeyWithProof) external; function removeBlsPubKeys(uint32[] memory indices) external; function updateSignAddress(address newSignAddress) external; function subscribe(uint32 chainID) external; function unsubscribe(uint32 chainID) external; function unsubscribeByAdmin(address[] memory operators, uint32 chainID) external; function deregister() external; function owner() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; interface IVoteWeigher { struct TokenMultiplier { address token; uint96 multiplier; } function addQuorumMultiplier(uint8 quorumNumber, TokenMultiplier[] memory multipliers) external; function removeQuorumMultiplier(uint8 quorumNumber) external; function updateQuorumMultiplier(uint8 quorumNumber, uint256 index, TokenMultiplier memory multiplier) external; function weightOfOperator(uint8 quorumNumber, address operator) external view returns (uint96); function getTokenList() external view returns (address[] memory); function getTokenListForQuorumNumbers(uint8[] memory quorumNumbers_) external view returns (address[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {BN254} from "eigenlayer-middleware/libraries/BN254.sol"; import "../interfaces/IBLSKeyChecker.sol"; abstract contract BLSKeyChecker is IBLSKeyChecker { using BN254 for BN254.G1Point; uint256 internal constant PAIRING_EQUALITY_CHECK_GAS = 120000; bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); bytes32 public constant BLS_KEY_WITH_PROOF_TYPEHASH = keccak256("BLSKeyWithProof(address operator,bytes32 salt,uint256 expiry)"); struct SaltStorage { mapping(address => mapping(bytes32 => bool)) operatorSalts; } // keccak256(abi.encode(uint256(keccak256("lagrange.blskeychecker.storage")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant SaltStorageLocation = 0x51615ea63289f14fdd891b383e2929b2f73c675cf292e602b5fceb059f7a4700; function _getSaltStorage() private pure returns (SaltStorage storage $) { assembly { $.slot := SaltStorageLocation } } function _validateBLSKeyWithProof(address operator, BLSKeyWithProof memory keyWithProof) internal { require( keyWithProof.expiry >= block.timestamp, "BLSKeyChecker.checkBLSKeyWithProof: operator signature expired" ); SaltStorage storage $ = _getSaltStorage(); require(!$.operatorSalts[operator][keyWithProof.salt], "BLSKeyChecker.checkBLSKeyWithProof: salt already spent"); $.operatorSalts[operator][keyWithProof.salt] = true; BN254.G1Point memory aggG1 = BN254.G1Point(0, 0); for (uint256 i = 0; i < keyWithProof.blsG1PublicKeys.length; i++) { aggG1 = aggG1.plus(BN254.G1Point(keyWithProof.blsG1PublicKeys[i][0], keyWithProof.blsG1PublicKeys[i][1])); } BN254.G2Point memory aggG2 = BN254.G2Point(keyWithProof.aggG2PublicKey[0], keyWithProof.aggG2PublicKey[1]); // check the pairing equation e(g1, aggG2) == e(aggG1, -g2) // to ensure that the aggregated G2 public key is correct (bool pairing, bool valid) = BN254.safePairing(BN254.generatorG1(), aggG2, aggG1, BN254.negGeneratorG2(), PAIRING_EQUALITY_CHECK_GAS); require(pairing && valid, "BLSKeyChecker.checkBLSKeyWithProof: invalid BLS key"); BN254.G1Point memory sig = BN254.G1Point(keyWithProof.signature[0], keyWithProof.signature[1]); BN254.G1Point memory msgHash = BN254.hashToG1(calculateKeyWithProofHash(operator, keyWithProof.salt, keyWithProof.expiry)); // check the BLS signature (pairing, valid) = BN254.safePairing(sig, BN254.negGeneratorG2(), msgHash, aggG2, PAIRING_EQUALITY_CHECK_GAS); require(pairing && valid, "BLSKeyChecker.checkBLSKeyWithProof: invalid BLS signature"); } function isSaltSpent(address operator, bytes32 salt) public view returns (bool) { SaltStorage storage $ = _getSaltStorage(); return $.operatorSalts[operator][salt]; } function calculateKeyWithProofHash(address operator, bytes32 salt, uint256 expiry) public view returns (bytes32) { bytes32 structHash = keccak256(abi.encode(BLS_KEY_WITH_PROOF_TYPEHASH, operator, salt, expiry)); bytes32 digestHash = keccak256(abi.encodePacked("\x19\x01", domainSeparator(), structHash)); return digestHash; } function domainSeparator() public view returns (bytes32) { return keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256("Lagrange State Committee"), block.chainid, address(this))); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; interface IBLSKeyChecker { struct BLSKeyWithProof { uint256[2][] blsG1PublicKeys; uint256[2][2] aggG2PublicKey; uint256[2] signature; bytes32 salt; uint256 expiry; } function isSaltSpent(address operator, bytes32 salt) external view returns (bool); function calculateKeyWithProofHash(address operator, bytes32 salt, uint256 expiry) external view returns (bytes32); function domainSeparator() external view returns (bytes32); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; /** * @title The interface for common signature utilities. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service */ interface ISignatureUtils { // @notice Struct that bundles together a signature and an expiration time for the signature. Used primarily for stack management. struct SignatureWithExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the expiration timestamp (UTC) of the signature uint256 expiry; } // @notice Struct that bundles together a signature, a salt for uniqueness, and an expiration time for the signature. Used primarily for stack management. struct SignatureWithSaltAndExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the salt used to generate the signature bytes32 salt; // the expiration timestamp (UTC) of the signature uint256 expiry; } }
// SPDX-License-Identifier: MIT // several functions are taken or adapted from https://github.com/HarryR/solcrypto/blob/master/contracts/altbn128.sol (MIT license): // Copyright 2017 Christian Reitwiessner // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // The remainder of the code in this library is written by LayrLabs Inc. and is also under an MIT license pragma solidity =0.8.12; /** * @title Library for operations on the BN254 elliptic curve. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice Contains BN254 parameters, common operations (addition, scalar mul, pairing), and BLS signature functionality. */ library BN254 { // modulus for the underlying field F_p of the elliptic curve uint256 internal constant FP_MODULUS = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // modulus for the underlying field F_r of the elliptic curve uint256 internal constant FR_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; struct G1Point { uint256 X; uint256 Y; } // Encoding of field elements is: X[1] * i + X[0] struct G2Point { uint256[2] X; uint256[2] Y; } function generatorG1() internal pure returns (G1Point memory) { return G1Point(1, 2); } // generator of group G2 /// @dev Generator point in F_q2 is of the form: (x0 + ix1, y0 + iy1). uint256 internal constant G2x1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; uint256 internal constant G2x0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; uint256 internal constant G2y1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; uint256 internal constant G2y0 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; /// @notice returns the G2 generator /// @dev mind the ordering of the 1s and 0s! /// this is because of the (unknown to us) convention used in the bn254 pairing precompile contract /// "Elements a * i + b of F_p^2 are encoded as two elements of F_p, (a, b)." /// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-197.md#encoding function generatorG2() internal pure returns (G2Point memory) { return G2Point([G2x1, G2x0], [G2y1, G2y0]); } // negation of the generator of group G2 /// @dev Generator point in F_q2 is of the form: (x0 + ix1, y0 + iy1). uint256 internal constant nG2x1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; uint256 internal constant nG2x0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; uint256 internal constant nG2y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052; uint256 internal constant nG2y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653; function negGeneratorG2() internal pure returns (G2Point memory) { return G2Point([nG2x1, nG2x0], [nG2y1, nG2y0]); } bytes32 internal constant powersOfTauMerkleRoot = 0x22c998e49752bbb1918ba87d6d59dd0e83620a311ba91dd4b2cc84990b31b56f; /** * @param p Some point in G1. * @return The negation of `p`, i.e. p.plus(p.negate()) should be zero. */ function negate(G1Point memory p) internal pure returns (G1Point memory) { // The prime q in the base field F_q for G1 if (p.X == 0 && p.Y == 0) { return G1Point(0, 0); } else { return G1Point(p.X, FP_MODULUS - (p.Y % FP_MODULUS)); } } /** * @return r the sum of two points of G1 */ function plus(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { uint256[4] memory input; input[0] = p1.X; input[1] = p1.Y; input[2] = p2.X; input[3] = p2.Y; bool success; // solium-disable-next-line security/no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 6, input, 0x80, r, 0x40) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } require(success, "ec-add-failed"); } /** * @notice an optimized ecMul implementation that takes O(log_2(s)) ecAdds * @param p the point to multiply * @param s the scalar to multiply by * @dev this function is only safe to use if the scalar is 9 bits or less */ function scalar_mul_tiny(BN254.G1Point memory p, uint16 s) internal view returns (BN254.G1Point memory) { require(s < 2**9, "scalar-too-large"); // if s is 1 return p if(s == 1) { return p; } // the accumulated product to return BN254.G1Point memory acc = BN254.G1Point(0, 0); // the 2^n*p to add to the accumulated product in each iteration BN254.G1Point memory p2n = p; // value of most significant bit uint16 m = 1; // index of most significant bit uint8 i = 0; //loop until we reach the most significant bit while(s >= m){ unchecked { // if the current bit is 1, add the 2^n*p to the accumulated product if ((s >> i) & 1 == 1) { acc = plus(acc, p2n); } // double the 2^n*p for the next iteration p2n = plus(p2n, p2n); // increment the index and double the value of the most significant bit m <<= 1; ++i; } } // return the accumulated product return acc; } /** * @return r the product of a point on G1 and a scalar, i.e. * p == p.scalar_mul(1) and p.plus(p) == p.scalar_mul(2) for all * points p. */ function scalar_mul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) { uint256[3] memory input; input[0] = p.X; input[1] = p.Y; input[2] = s; bool success; // solium-disable-next-line security/no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 7, input, 0x60, r, 0x40) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } require(success, "ec-mul-failed"); } /** * @return The result of computing the pairing check * e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 * For example, * pairing([P1(), P1().negate()], [P2(), P2()]) should return true. */ function pairing( G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2 ) internal view returns (bool) { G1Point[2] memory p1 = [a1, b1]; G2Point[2] memory p2 = [a2, b2]; uint256[12] memory input; for (uint256 i = 0; i < 2; i++) { uint256 j = i * 6; input[j + 0] = p1[i].X; input[j + 1] = p1[i].Y; input[j + 2] = p2[i].X[0]; input[j + 3] = p2[i].X[1]; input[j + 4] = p2[i].Y[0]; input[j + 5] = p2[i].Y[1]; } uint256[1] memory out; bool success; // solium-disable-next-line security/no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 8, input, mul(12, 0x20), out, 0x20) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } require(success, "pairing-opcode-failed"); return out[0] != 0; } /** * @notice This function is functionally the same as pairing(), however it specifies a gas limit * the user can set, as a precompile may use the entire gas budget if it reverts. */ function safePairing( G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2, uint256 pairingGas ) internal view returns (bool, bool) { G1Point[2] memory p1 = [a1, b1]; G2Point[2] memory p2 = [a2, b2]; uint256[12] memory input; for (uint256 i = 0; i < 2; i++) { uint256 j = i * 6; input[j + 0] = p1[i].X; input[j + 1] = p1[i].Y; input[j + 2] = p2[i].X[0]; input[j + 3] = p2[i].X[1]; input[j + 4] = p2[i].Y[0]; input[j + 5] = p2[i].Y[1]; } uint256[1] memory out; bool success; // solium-disable-next-line security/no-inline-assembly assembly { success := staticcall(pairingGas, 8, input, mul(12, 0x20), out, 0x20) } //Out is the output of the pairing precompile, either 0 or 1 based on whether the two pairings are equal. //Success is true if the precompile actually goes through (aka all inputs are valid) return (success, out[0] != 0); } /// @return hashedG1 the keccak256 hash of the G1 Point /// @dev used for BLS signatures function hashG1Point(BN254.G1Point memory pk) internal pure returns (bytes32 hashedG1) { assembly { mstore(0, mload(pk)) mstore(0x20, mload(add(0x20, pk))) hashedG1 := keccak256(0, 0x40) } } /// @return the keccak256 hash of the G2 Point /// @dev used for BLS signatures function hashG2Point( BN254.G2Point memory pk ) internal pure returns (bytes32) { return keccak256(abi.encodePacked(pk.X[0], pk.X[1], pk.Y[0], pk.Y[1])); } /** * @notice adapted from https://github.com/HarryR/solcrypto/blob/master/contracts/altbn128.sol */ function hashToG1(bytes32 _x) internal view returns (G1Point memory) { uint256 beta = 0; uint256 y = 0; uint256 x = uint256(_x) % FP_MODULUS; while (true) { (beta, y) = findYFromX(x); // y^2 == beta if( beta == mulmod(y, y, FP_MODULUS) ) { return G1Point(x, y); } x = addmod(x, 1, FP_MODULUS); } return G1Point(0, 0); } /** * Given X, find Y * * where y = sqrt(x^3 + b) * * Returns: (x^3 + b), y */ function findYFromX(uint256 x) internal view returns (uint256, uint256) { // beta = (x^3 + b) % p uint256 beta = addmod(mulmod(mulmod(x, x, FP_MODULUS), x, FP_MODULUS), 3, FP_MODULUS); // y^2 = x^3 + b // this acts like: y = sqrt(beta) = beta^((p+1) / 4) uint256 y = expMod(beta, 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52, FP_MODULUS); return (beta, y); } function expMod(uint256 _base, uint256 _exponent, uint256 _modulus) internal view returns (uint256 retval) { bool success; uint256[1] memory output; uint[6] memory input; input[0] = 0x20; // baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) input[1] = 0x20; // expLen = new(big.Int).SetBytes(getData(input, 32, 32)) input[2] = 0x20; // modLen = new(big.Int).SetBytes(getData(input, 64, 32)) input[3] = _base; input[4] = _exponent; input[5] = _modulus; assembly { success := staticcall(sub(gas(), 2000), 5, input, 0xc0, output, 0x20) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } require(success, "BN254.expMod: call failure"); return output[0]; } }
{ "remappings": [ "@openzeppelin-upgrades/=lib/openzeppelin-contracts-upgradeable/", "@openzeppelin/=lib/openzeppelin-contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/", "eigenlayer-middleware/=lib/eigenlayer-middleware/src/", "src/=lib/eigenlayer-middleware/src/", "forge-std/=lib/forge-std/src/", "@safe/=lib/safe-smart-account/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "safe-smart-account/=lib/safe-smart-account/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
[{"inputs":[{"internalType":"contract ILagrangeService","name":"_service","type":"address"},{"internalType":"contract IVoteWeigher","name":"_voteWeigher","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"uint256","name":"orgLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"added","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"removed","type":"uint256"}],"name":"BlsKeyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainID","type":"uint256"},{"indexed":true,"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"genesisBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"freezeDuration","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"minWeight","type":"uint96"},{"indexed":false,"internalType":"uint96","name":"maxWeight","type":"uint96"}],"name":"InitCommittee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"signAddress","type":"address"}],"name":"SignAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"epochNumber","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"current","type":"bytes32"}],"name":"UpdateCommittee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainID","type":"uint256"},{"indexed":true,"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"indexed":false,"internalType":"int256","name":"l1Bias","type":"int256"},{"indexed":false,"internalType":"uint256","name":"genesisBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"freezeDuration","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"minWeight","type":"uint96"},{"indexed":false,"internalType":"uint96","name":"maxWeight","type":"uint96"}],"name":"UpdateCommitteeParams","type":"event"},{"inputs":[],"name":"BLS_KEY_WITH_PROOF_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INNER_NODE_PREFIX","outputs":[{"internalType":"bytes1","name":"","type":"bytes1"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEAF_NODE_PREFIX","outputs":[{"internalType":"bytes1","name":"","type":"bytes1"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"uint256[2][]","name":"blsG1PublicKeys","type":"uint256[2][]"},{"internalType":"uint256[2][2]","name":"aggG2PublicKey","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"signature","type":"uint256[2]"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"internalType":"struct IBLSKeyChecker.BLSKeyWithProof","name":"blsKeyWithProof","type":"tuple"}],"name":"addBlsPubKeys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"signAddress","type":"address"},{"components":[{"internalType":"uint256[2][]","name":"blsG1PublicKeys","type":"uint256[2][]"},{"internalType":"uint256[2][2]","name":"aggG2PublicKey","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"signature","type":"uint256[2]"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"internalType":"struct IBLSKeyChecker.BLSKeyWithProof","name":"blsKeyWithProof","type":"tuple"}],"name":"addOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"calculateKeyWithProofHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainIDs","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"committeeAddrs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"committeeParams","outputs":[{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"int256","name":"l1Bias","type":"int256"},{"internalType":"uint256","name":"genesisBlock","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"freezeDuration","type":"uint256"},{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint96","name":"minWeight","type":"uint96"},{"internalType":"uint96","name":"maxWeight","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"committees","outputs":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"uint224","name":"updatedBlock","type":"uint224"},{"internalType":"uint32","name":"leafCount","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"opAddr","type":"address"},{"internalType":"uint32","name":"chainID","type":"uint32"}],"name":"getBlsPubKeyVotingPowers","outputs":[{"internalType":"uint96[]","name":"individualVotingPowers","type":"uint96[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getBlsPubKeys","outputs":[{"internalType":"uint256[2][]","name":"","type":"uint256[2][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getCommittee","outputs":[{"components":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"uint224","name":"updatedBlock","type":"uint224"},{"internalType":"uint32","name":"leafCount","type":"uint32"}],"internalType":"struct ILagrangeCommittee.CommitteeData","name":"currentCommittee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"},{"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"getEpochInterval","outputs":[{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"freezeBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getEpochNumber","outputs":[{"internalType":"uint256","name":"epochNumber","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"opAddr","type":"address"},{"internalType":"uint32","name":"chainID","type":"uint32"}],"name":"getOperatorVotingPower","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getTokenListForOperator","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"}],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"isSaltSpent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isUnregisterable","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"},{"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"isUpdatable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operatorsStatus","outputs":[{"internalType":"address","name":"signAddress","type":"address"},{"internalType":"uint8","name":"subscribedChainCount","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"},{"internalType":"uint256","name":"genesisBlock","type":"uint256"},{"internalType":"uint256","name":"epochPeriod","type":"uint256"},{"internalType":"uint256","name":"freezeDuration","type":"uint256"},{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint96","name":"minWeight","type":"uint96"},{"internalType":"uint96","name":"maxWeight","type":"uint96"}],"name":"registerChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint32[]","name":"indices","type":"uint32[]"}],"name":"removeBlsPubKeys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"removeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"},{"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"revertEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"service","outputs":[{"internalType":"contract ILagrangeService","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint32","name":"chainID","type":"uint32"}],"name":"subscribeChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"address","name":"","type":"address"}],"name":"subscribedChains","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":"operators","type":"address[]"},{"internalType":"uint32","name":"chainID","type":"uint32"}],"name":"unsubscribeByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint32","name":"chainID","type":"uint32"}],"name":"unsubscribeChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"},{"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint32","name":"index","type":"uint32"},{"components":[{"internalType":"uint256[2][]","name":"blsG1PublicKeys","type":"uint256[2][]"},{"internalType":"uint256[2][2]","name":"aggG2PublicKey","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"signature","type":"uint256[2]"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"internalType":"struct IBLSKeyChecker.BLSKeyWithProof","name":"blsKeyWithProof","type":"tuple"}],"name":"updateBlsPubKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"chainID","type":"uint32"},{"internalType":"int256","name":"l1Bias","type":"int256"},{"internalType":"uint256","name":"genesisBlock","type":"uint256"},{"internalType":"uint256","name":"epochPeriod","type":"uint256"},{"internalType":"uint256","name":"freezeDuration","type":"uint256"},{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint96","name":"minWeight","type":"uint96"},{"internalType":"uint96","name":"maxWeight","type":"uint96"}],"name":"updateChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256[2][]","name":"blsG1PublicKeys","type":"uint256[2][]"},{"internalType":"uint256[2][2]","name":"aggG2PublicKey","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"signature","type":"uint256[2]"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"internalType":"struct IBLSKeyChecker.BLSKeyWithProof","name":"blsKeyWithProof","type":"tuple"}],"name":"updateSequencerBlsPubKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"newSignAddress","type":"address"}],"name":"updateSignAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"updatedEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voteWeigher","outputs":[{"internalType":"contract IVoteWeigher","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162005d9038038062005d90833981016040819052620000349162000134565b6001600160a01b03808316608052811660a0526200005162000059565b505062000173565b600054610100900460ff1615620000c65760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116101562000119576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b03811681146200013157600080fd5b50565b600080604083850312156200014857600080fd5b825162000155816200011b565b602084015190925062000168816200011b565b809150509250929050565b60805160a051615b9c620001f4600039600081816108590152818161161b0152818161174501528181611b71015261348b0152600081816107ee015281816108db01528181610d76015281816110af0152818161138e015281816117f001528181611cba01528181611f54015281816122cd01526126ed0152615b9c6000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637285645511610151578063ac8a584a116100c3578063cfedf42711610087578063cfedf427146107d6578063d598d4c9146107e9578063def9e7d514610810578063ef03067314610854578063f2fde38b1461087b578063f698da251461088e57600080fd5b8063ac8a584a14610777578063bf988ab61461078a578063c4d66de81461079d578063c5f7c4e9146107b0578063c8491506146107c357600080fd5b8063935a9b6a11610115578063935a9b6a1461065457806395703d08146106675780639e224428146106be578063a43dd8dd146106d1578063a63490a2146106f1578063a6b150681461076457600080fd5b8063728564551461054c57806378d81d08146105f6578063829c7dd71461060957806385ab9a7a1461061c5780638da5cb5b1461062f57600080fd5b80633811db0d116101ea57806353b7a0ff116101ae57806353b7a0ff146104ad57806356bf7c25146104db5780635af1a88f146104fb5780636b11c38e14610526578063715018a614610539578063727cb30f1461054157600080fd5b80633811db0d146103db57806338fa59d1146104435780633bc72805146104675780633d6a26791461047a5780634db6f74a1461048d57600080fd5b806316c72b2f1161023c57806316c72b2f1461030f57806319a74c5f146103225780631de8d88e1461034c57806320606b701461038157806324ca7a48146103a85780632c36c718146103c857600080fd5b806309d23e24146102795780630c57b9d4146102a65780630e9f564b146102bb5780630f225b84146102ce57806313538c7f146102fc575b600080fd5b61028c610287366004614fa8565b610896565b60405163ffffffff90911681526020015b60405180910390f35b6102b96102b4366004615021565b6108d0565b005b6102b96102c936600461508e565b610d6b565b6102e16102dc3660046150c3565b610e6b565b6040805193845260208401929092529082015260600161029d565b6102b961030a366004615113565b611011565b6102b961031d3660046151ad565b6110a4565b61033561033036600461520e565b611179565b60408051921515835260208301919091520161029d565b6103737f1a3843f7e4c22d9c427c97a0094da0bc4b96584c20d784e647bac3bdf2f8e5a081565b60405190815260200161029d565b6103737f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6103bb6103b636600461508e565b61132a565b60405161029d919061522b565b6102b96103d636600461526c565b611383565b6104336103e93660046152a5565b6001600160a01b039190911660009081527f51615ea63289f14fdd891b383e2929b2f73c675cf292e602b5fceb059f7a470060209081526040808320938352929052205460ff1690565b604051901515815260200161029d565b61044e600160f81b81565b6040516001600160f81b0319909116815260200161029d565b6102b96104753660046150c3565b61148a565b6103356104883660046152c3565b611499565b61037361049b3660046152c3565b606b6020526000908152604090205481565b6104336104bb3660046152de565b606c60209081526000928352604080842090915290825290205460ff1681565b6104ee6104e936600461520e565b6114c9565b60405161029d91906152fa565b61050e61050936600461508e565b61169e565b6040516001600160601b03909116815260200161029d565b6102b961053436600461508e565b6117e5565b6102b9611c59565b61044e600160f91b81565b6105ac61055a3660046152c3565b606660205260009081526040902080546001820154600283015460038401546004850154600590950154939492939192909160ff8116906001600160601b036101008204811691600160681b90041688565b604080519889526020890197909752958701949094526060860192909252608085015260ff1660a08401526001600160601b0390811660c08401521660e08201526101000161029d565b6103736106043660046150c3565b611c6d565b6102b961061736600461533b565b611caf565b61043361062a3660046150c3565b611f2b565b6033546001600160a01b03165b6040516001600160a01b03909116815260200161029d565b6102b9610662366004615369565b611f49565b61069d61067536600461520e565b606a60205260009081526040902080546002909101546001600160a01b039091169060ff1682565b604080516001600160a01b03909316835260ff90911660208301520161029d565b6103736106cc3660046153bc565b6120ab565b6106e46106df36600461520e565b612162565b60405161029d91906153f1565b61073b6106ff3660046150c3565b6067602090815260009283526040808420909152908252902080546001909101546001600160e01b03811690600160e01b900463ffffffff1683565b604080519384526001600160e01b03909216602084015263ffffffff169082015260600161029d565b6102b96107723660046150c3565b6121f8565b6102b961078536600461520e565b6122c2565b61063c6107983660046150c3565b612358565b6102b96107ab36600461520e565b612390565b6102b96107be36600461545a565b612528565b6102b96107d136600461548e565b612644565b6102b96107e4366004615505565b6126e2565b61063c7f000000000000000000000000000000000000000000000000000000000000000081565b61082361081e3660046150c3565b612749565b60408051825181526020808401516001600160e01b0316908201529181015163ffffffff169082015260600161029d565b61063c7f000000000000000000000000000000000000000000000000000000000000000081565b6102b961088936600461520e565b6127cd565b610373612843565b606581815481106108a657600080fd5b9060005260206000209060089182820401919006600402915054906101000a900463ffffffff1681565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109215760405162461bcd60e51b815260040161091890615554565b60405180910390fd5b6001600160a01b0383166000908152606a6020908152604080832060010180548251818502810185019093528083529192909190849084015b828210156109aa5760008481526020902060408051808201918290529160028581029091019182845b8154815260200190600101908083116109835750505050508152602001906001019061095a565b505082519293505050828111610a1c5760405162461bcd60e51b815260206004820152603160248201527f496e76616c696420696e6469636573206c656e6774682c20424c53206b6579736044820152701031b0b73737ba1031329032b6b83a3c9760791b6064820152608401610918565b60005b83811015610b6257848482818110610a3957610a396155a1565b9050602002016020810190610a4e91906152c3565b63ffffffff168211610a925760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610918565b600083868684818110610aa757610aa76155a1565b9050602002016020810190610abc91906152c3565b63ffffffff1681518110610ad257610ad26155a1565b6020026020010151600060028110610aec57610aec6155a1565b6020020152600083868684818110610b0657610b066155a1565b9050602002016020810190610b1b91906152c3565b63ffffffff1681518110610b3157610b316155a1565b6020026020010151600160028110610b4b57610b4b6155a1565b602002015280610b5a816155cd565b915050610a1f565b506000805b82811015610c3f57838181518110610b8157610b816155a1565b6020026020010151600060028110610b9b57610b9b6155a1565b6020020151151580610bdc5750838181518110610bba57610bba6155a1565b6020026020010151600160028110610bd457610bd46155a1565b602002015115155b15610c2d57838181518110610bf357610bf36155a1565b6020026020010151848363ffffffff1681518110610c1357610c136155a1565b60200260200101819052508180610c29906155e8565b9250505b80610c37816155cd565b915050610b67565b5060008163ffffffff166001600160401b03811115610c6057610c6061560c565b604051908082528060200260200182016040528015610c9957816020015b610c86614d53565b815260200190600190039081610c7e5790505b50905060005b8263ffffffff16811015610cf757848181518110610cbf57610cbf6155a1565b6020026020010151828281518110610cd957610cd96155a1565b60200260200101819052508080610cef906155cd565b915050610c9f565b506001600160a01b0387166000908152606a602090815260409091208251610d2792600190920191840190614d71565b5060408051848152600060208201529081018690526001600160a01b03881690600080516020615b278339815191529060600160405180910390a250505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610db35760405162461bcd60e51b815260040161091890615554565b63ffffffff81166000908152606c602090815260408083206001600160a01b038616845290915290205460ff16610dfc5760405162461bcd60e51b815260040161091890615622565b600080610e0883611499565b915091508115610e5a5760405162461bcd60e51b815260206004820152601e60248201527f5468652064656469636174656420636861696e206973206c6f636b65642e00006044820152606401610918565b610e658484836128c2565b50505050565b63ffffffff821660008181526066602090815260408083208151610100808201845282548252600183015482860152600283015482850152600383015460608301526004830154608083015260059092015460ff811660a08301526001600160601b03928104831660c0830152600160681b900490911660e0820152938352606b9091528120549091829182919085610f4457815194508015610f1857610f1387600161297c565b610f29565b60608201518251610f299190615667565b9250816080015183610f3b919061567f565b9350505061100a565b808611610f9f57610f55878761297c565b9450858114610f7757610f7287610f6d886001615667565b61297c565b610f86565b6060820151610f869086615667565b9250816080015183610f98919061567f565b9350611007565b6000808211610faf578251610fb9565b610fb9888361297c565b6060840151909150610fcb838961567f565b610fd59190615696565b610fdf9082615667565b9550826060015186610ff19190615667565b9350826080015184611003919061567f565b9450505b50505b9250925092565b6110196129ad565b63ffffffff8816600090815260666020526040902054806110745760405162461bcd60e51b815260206004820152601560248201527410da185a5b881b9bdd081a5b9a5d1a585b1a5e9959605a1b6044820152606401610918565b61107e8383612a07565b6110888686612a81565b6110998989838a8a8a8a8a8a612ad0565b505050505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110ec5760405162461bcd60e51b815260040161091890615554565b6111616110f982806156b5565b808060200260200160405190810160405280939291908181526020016000905b828210156111575760408051808201825290808402870190600290839083908082843760009201919091525050508152600190910190602001611119565b5050505050612c74565b611174838361116f8461583a565b612d94565b505050565b6001600160a01b038082166000908152606a602090815260408083208151608081018352815490951685526001810180548351818602810186019094528084529495869586959194858301939092909190879084015b8282101561121f5760008481526020902060408051808201918290529160028581029091019182845b8154815260200190600101908083116111f8575050505050815260200190600101906111cf565b50505090825250600282015460ff16602080830191909152600383018054604080518285028101850182528281529401939260009084015b8282101561129c5760008481526020908190206040805180820190915260028502909101805463ffffffff168252600190810154828401529083529092019101611257565b50505091525050604081015190915060ff16156112bf5750600093849350915050565b606081015151600090815b8181101561131b576000846060015182815181106112ea576112ea6155a1565b60200260200101519050838160200151111561130857806020015193505b5080611313816155cd565b9150506112ca565b50600196919550909350505050565b60606000611338848461169e565b63ffffffff84166000908152606660205260409020600501549091506001600160601b036101008204811691600160681b900416611377838383612f6d565b93505050505b92915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113cb5760405162461bcd60e51b815260040161091890615554565b6001600160a01b0382166000908152606a60205260409020600101546114335760405162461bcd60e51b815260206004820152601b60248201527f4f70657261746f72206973206e6f7420726567697374657265642e00000000006044820152606401610918565b6001600160a01b038281166000818152606a602052604080822080546001600160a01b0319169486169485179055517ff29351472086a2d8b1af521f96d65142d14518260a62923a07aa7c9e3c752d849190a35050565b611495828243613109565b5050565b60008060006114a88443613806565b90506000806114b78684610e6b565b43919091119890975095505050505050565b6065546001600160a01b0382166000908152606a6020526040812060020154606092919060ff166001600160401b038111156115075761150761560c565b604051908082528060200260200182016040528015611530578160200160208202803683370190505b5090506000805b8381101561160357600060658281548110611554576115546155a1565b6000918252602080832060088304015460079092166004026101000a90910463ffffffff16808352606c825260408084206001600160a01b038c16855290925291205490915060ff16156115f05763ffffffff811660009081526066602052604090206005015460ff1684846115c9816155cd565b9550815181106115db576115db6155a1565b602002602001019060ff16908160ff16815250505b50806115fb816155cd565b915050611537565b50604051635ce8f06760e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635ce8f0679061165090859060040161591b565b600060405180830381865afa15801561166d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116959190810190615956565b95945050505050565b63ffffffff81166000908152606660209081526040808320815161010080820184528254825260018301548286015260028301548285015260038301546060830152600480840154608084015260059093015460ff811660a084018190529181046001600160601b0390811660c0850152600160681b9091041660e08301528351631b48130b60e31b8152928301526001600160a01b0387811660248401529251909385937f0000000000000000000000000000000000000000000000000000000000000000169263da40985892604480830193928290030181865afa15801561178c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b091906159ef565b6001600160a01b0386166000908152606a602052604090206001015460c084015160e0850151929350611695928491906139c9565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461182d5760405162461bcd60e51b815260040161091890615554565b63ffffffff811660009081526066602052604090205461189e5760405162461bcd60e51b815260206004820152602660248201527f5468652064656469636174656420636861696e206973206e6f742072656769736044820152653a32b932b21760d11b6064820152608401610918565b60006118a982611499565b50905080156118fa5760405162461bcd60e51b815260206004820152601e60248201527f5468652064656469636174656420636861696e206973206c6f636b65642e00006044820152606401610918565b6001600160a01b0383166000908152606a6020908152604080832060030180548251818502810185019093528083529192909190849084015b828210156119785760008481526020908190206040805180820190915260028502909101805463ffffffff168252600190810154828401529083529092019101611933565b5050825192935060009150505b81811015611a3d5760008382815181106119a1576119a16155a1565b602002602001015190508563ffffffff16816000015163ffffffff161415611a2a5743816020015110611a2a5760405162461bcd60e51b815260206004820152602b60248201527f5468652064656463696174656420636861696e206973207768696c6520756e7360448201526a3ab139b1b934b134b7339760a91b6064820152608401610918565b5080611a35816155cd565b915050611985565b5063ffffffff84166000908152606c602090815260408083206001600160a01b038916845290915290205460ff1615611acb5760405162461bcd60e51b815260206004820152602a60248201527f5468652064656469636174656420636861696e20697320616c726561647920736044820152693ab139b1b934b132b21760b11b6064820152608401610918565b63ffffffff84166000908152606660209081526040808320815161010080820184528254825260018301548286015260028301548285015260038301546060830152600480840154608084015260059093015460ff811660a084018190529181046001600160601b0390811660c0850152600160681b9091041660e08301528351631b48130b60e31b8152928301526001600160a01b038a8116602484015292519094937f00000000000000000000000000000000000000000000000000000000000000009093169263da40985892604480820193918290030181865afa158015611bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bde91906159ef565b90508160c001516001600160601b0316816001600160601b03161015611c465760405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e7420566f74652057656967687400000000000000006044820152606401610918565b611c508787613a1b565b50505050505050565b611c616129ad565b611c6b6000613aca565b565b6000611c798383613806565b905080158015611ca1575063ffffffff83166000908152606660205260409020600201548210155b1561137d5750600192915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611cf75760405162461bcd60e51b815260040161091890615554565b611d0983611d048361583a565b613b1c565b611d1381806156b5565b9050600114611d645760405162461bcd60e51b815260206004820152601d60248201527f4c656e6774682073686f756c64206265203120666f72207570646174650000006044820152606401610918565b6001600160a01b0383166000908152606a60205260409020600101805463ffffffff84168111611dc65760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610918565b611e9082805480602002602001604051908101604052809291908181526020016000905b82821015611e3a5760008481526020902060408051808201918290529160028581029091019182845b815481526020019060010190808311611e1357505050505081526020019060010190611dea565b50611e4b92508791508190506156b5565b6000818110611e5c57611e5c6155a1565b9050604002016002806020026040519081016040528092919082600260200280828437600092019190915250613efc915050565b611e9a83806156b5565b6000818110611eab57611eab6155a1565b905060400201828563ffffffff1681548110611ec957611ec96155a1565b9060005260206000209060020201906002611ee5929190614dc7565b5060408051828152600160208201819052918101919091526001600160a01b03861690600080516020615b27833981519152906060015b60405180910390a25050505050565b600080611f3d846102dc60018661567f565b50431195945050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611f915760405162461bcd60e51b815260040161091890615554565b8160005b818110156120a4576000858583818110611fb157611fb16155a1565b9050602002016020810190611fc6919061520e565b63ffffffff85166000908152606c602090815260408083206001600160a01b038516845290915290205490915060ff166120125760405162461bcd60e51b815260040161091890615622565b63ffffffff84166000908152606c602090815260408083206001600160a01b03851684529091529020805460ff1916905561204d8482613fd7565b6001600160a01b0381166000908152606a60205260408120600201805460ff169161207783615a0c565b91906101000a81548160ff021916908360ff1602179055505050808061209c906155cd565b915050611f95565b5050505050565b604080517f1a3843f7e4c22d9c427c97a0094da0bc4b96584c20d784e647bac3bdf2f8e5a060208201526001600160a01b038516918101919091526060810183905260808101829052600090819060a001604051602081830303815290604052805190602001209050600061211e612843565b60405161190160f01b602082015260228101919091526042810183905260620160408051601f198184030181529190528051602090910120925050505b9392505050565b6001600160a01b0381166000908152606a60209081526040808320600101805482518185028101850190935280835260609492939192909184015b828210156121ed5760008481526020902060408051808201918290529160028581029091019182845b8154815260200190600101908083116121c65750505050508152602001906001019061219d565b505050509050919050565b6122006129ad565b63ffffffff82166000908152606b6020526040902054811461226f5760405162461bcd60e51b815260206004820152602260248201527f5468652065706f63684e756d626572206973206e6f7420746865206c617465736044820152613a1760f11b6064820152608401610918565b63ffffffff8216600090815260676020908152604080832084845290915281208181556001908101919091556122a5908261567f565b63ffffffff9092166000908152606b602052604090209190915550565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461230a5760405162461bcd60e51b815260040161091890615554565b6001600160a01b0381166000908152606a6020526040812080546001600160a01b03191681559061233e6001830182614e01565b60028201805460ff19169055611174600383016000614e22565b6068602052816000526040600020818154811061237457600080fd5b6000918252602090912001546001600160a01b03169150829050565b600054610100900460ff16158080156123b05750600054600160ff909116105b806123ca5750303b1580156123ca575060005460ff166001145b61242d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610918565b6000805460ff191660011790558015612450576000805461ff0019166101001790555b60015b60148160ff16116124d5576124b060696000612470600185615a29565b60ff1660ff16815260200190815260200160002054606960006001856124969190615a29565b60ff1660ff168152602001908152602001600020546141bd565b60ff8216600090815260696020526040902055806124cd81615a4c565b915050612453565b506124df82613aca565b8015611495576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6125306129ad565b61253a81806156b5565b905060011461258b5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f6e65206b65792073686f756c642062652070726f76696465642e6044820152606401610918565b61259830611d048361583a565b6125a281806156b5565b306000908152606a602052604090206125c092600190910191614e43565b50306000908152606a60205260409020600101546126105760408051600080825260016020830152918101919091523090600080516020615b27833981519152906060015b60405180910390a250565b60408051600180825260208201819052918101919091523090600080516020615b2783398151915290606001612605565b50565b61264c6129ad565b63ffffffff8716600090815260666020526040902054156126bf5760405162461bcd60e51b815260206004820152602760248201527f436f6d6d69747465652068617320616c7265616479206265656e20696e69746960448201526630b634bd32b21760c91b6064820152608401610918565b6126c98282612a07565b6126d38585612a81565b611c50878787878787876141fc565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461272a5760405162461bcd60e51b815260040161091890615554565b6127376110f982806156b5565b611495826127448361583a565b6144a6565b60408051606081018252600080825260208201819052918101829052906127708484611c6d565b63ffffffff9485166000908152606760209081526040808320938352928152908290208251606081018452815481526001909101546001600160e01b03811692820192909252600160e01b90910490951690850152509192915050565b6127d56129ad565b6001600160a01b03811661283a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610918565b61264181613aca565b604080517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86660208201527fa1cdac95fbc855fc66c2df41a0f389eb0dff513790ade024e7ad056efd60a6f49181019190915246606082015230608082015260009060a00160405160208183030381529060405280519060200120905090565b63ffffffff8281166000818152606c602090815260408083206001600160a01b03891684528252808320805460ff19169055606a825280832081518083019092529381528082018681526003850180546001818101835591865293852092516002948502909301805463ffffffff191693909716929092178655519401939093559181018054919260ff9092169161295983615a0c565b91906101000a81548160ff021916908360ff16021790555050610e658385613fd7565b63ffffffff91909116600090815260676020908152604080832093835292905220600101546001600160e01b031690565b6033546001600160a01b03163314611c6b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610918565b6000826001600160601b0316118015612a3c5750612a26826002615a6c565b6001600160601b0316816001600160601b031610155b6114955760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081b5a5b8bdb585e0815d95a59da1d60521b6044820152606401610918565b8082116114955760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420667265657a65206475726174696f6e0000000000000000006044820152606401610918565b6040518061010001604052808881526020018981526020018781526020018681526020018581526020018460ff168152602001836001600160601b03168152602001826001600160601b0316815250606660008b63ffffffff1663ffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548160ff021916908360ff16021790555060c08201518160050160016101000a8154816001600160601b0302191690836001600160601b0316021790555060e082015181600501600d6101000a8154816001600160601b0302191690836001600160601b031602179055509050508260ff168963ffffffff167fc0f5fe53277733159fe7a739f75b98e959a28a0859db2c46e04a5f4820b964008a8989898888604051612c61969594939291909586526020860194909452604085019290925260608401526001600160601b0390811660808401521660a082015260c00190565b60405180910390a3505050505050505050565b8051612cbb5760405162461bcd60e51b815260206004820152601660248201527522b6b83a3c9021262990283ab13634b19025b2bcb99760511b6044820152606401610918565b805160005b8181101561117457828181518110612cda57612cda6155a1565b6020026020010151600060028110612cf457612cf46155a1565b602002015115801590612d365750828181518110612d1457612d146155a1565b6020026020010151600160028110612d2e57612d2e6155a1565b602002015115155b612d825760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420424c53205075626c6963204b65792e0000000000000000006044820152606401610918565b80612d8c816155cd565b915050612cc0565b612d9e8382613b1c565b6001600160a01b0383166000908152606a6020526040812080546001600160a01b031916815590612dd26001830182614e01565b60028201805460ff19169055612dec600383016000614e22565b50506001600160a01b038381166000908152606a60205260408120600181015481546001600160a01b0319169386169390931781558351519092915b81811015612f2a57612ece84600101805480602002602001604051908101604052809291908181526020016000905b82821015612ea75760008481526020902060408051808201918290529160028581029091019182845b815481526020019060010190808311612e8057505050505081526020019060010190612e57565b5050505086600001518381518110612ec157612ec16155a1565b6020026020010151613efc565b8360010185600001518281518110612ee857612ee86155a1565b6020908102919091018101518254600181018455600093845291909220612f1792600292830290910191614e8a565b5080612f22816155cd565b915050612e28565b50604080518381526020810183905260008183015290516001600160a01b03881691600080516020615b27833981519152919081900360600190a2505050505050565b60606000612f7c85858561463a565b63ffffffff1690506000816001600160401b03811115612f9e57612f9e61560c565b604051908082528060200260200182016040528015612fc7578160200160208202803683370190505b50905081612fd857915061215b9050565b6000865b8686016001600160601b0316816001600160601b0316106130305785838380600101945081518110613010576130106155a1565b6001600160601b0390921660209283029190910190910152859003612fdc565b856001600160601b0316816001600160601b031611156130c35786838380600101945081518110613063576130636155a1565b60200260200101906001600160601b031690816001600160601b03168152505086810383838060010194508151811061309e5761309e6155a1565b60200260200101906001600160601b031690816001600160601b0316815250506130fd565b808383806001019450815181106130dc576130dc6155a1565b60200260200101906001600160601b031690816001600160601b0316815250505b50909695505050505050565b6131138383611f2b565b6131795760405162461bcd60e51b815260206004820152603160248201527f426c6f636b206e756d626572206973207072696f7220746f20636f6d6d69747460448201527032b290333932b2bd32903bb4b73237bb9760791b6064820152608401610918565b63ffffffff83166000908152606b6020526040902054829061319c906001615667565b146131f45760405162461bcd60e51b815260206004820152602260248201527f5468652065706f63684e756d626572206973206e6f742073657175656e746961604482015261361760f11b6064820152608401610918565b63ffffffff831660008181526066602090815260408083208151610100808201845282548252600183015482860152600283015482850152600383015460608301526004830154608083015260059092015460ff811660a083018190529281046001600160601b0390811660c08401819052600160681b9092041660e0830181905296865260688552838620805485518188028101880190965280865292979396919593949193919290918301828280156132d857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116132ba575b505083519394506001925060009150505b8281101561333b57606a6000858381518110613307576133076155a1565b6020908102919091018101516001600160a01b031682528101919091526040016000206001908101549290920191016132e9565b506000816001600160401b038111156133565761335661560c565b60405190808252806020026020018201604052801561337f578160200160208202803683370190505b50306000908152606a60205260408120600101549093509091501561342a57306000818152606a6020526040812060010180546134069392906133c4576133c46155a1565b600091825260209091206040805180820191829052926002908102909201919082845b8154815260200190600101908083116133e757505050505060006146db565b818381518110613418576134186155a1565b60209081029190910101526001909101905b60005b8381101561362d576000858281518110613449576134496155a1565b602002602001015190506000606a6000836001600160a01b03166001600160a01b031681526020019081526020016000209050600061353682600101805490507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663da4098588e876040518363ffffffff1660e01b81526004016134ee92919060ff9290921682526001600160a01b0316602082015260400190565b602060405180830381865afa15801561350b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352f91906159ef565b8c8c6139c9565b90508060005b6001600160601b0382161561361c5760008c8c016001600160601b0316836001600160601b03161061356f57508a613593565b8b6001600160601b0316836001600160601b0316111561359057508b613593565b50815b80830392506135f2868660010184815481106135b1576135b16155a1565b600091825260209091206040805180820191829052926002908102909201919082845b8154815260200190600101908083116135d4575050505050836146db565b888a81518110613604576136046155a1565b6020908102919091010152506001978801970161353c565b50506001909301925061342d915050565b50600082815b600182111561372d576001828101811c905b838110156136b55761368c866001830381518110613665576136656155a1565b602002602001015187838151811061367f5761367f6155a1565b60200260200101516141bd565b86600183901c815181106136a2576136a26155a1565b6020908102919091010152600201613645565b508260011660011415613723576137018560018503815181106136da576136da6155a1565b6020026020010151606960008560ff1660ff168152602001908152602001600020546141bd565b856001830381518110613716576137166155a1565b6020026020010181815250505b9150600101613633565b5083156137525782600081518110613747576137476155a1565b602002602001015191505b5063ffffffff8c811660009081526067602090815260408083208f84529091529020600181018054928616600160e01b026001600160e01b03909316929092179091558190556137a38c8c8c614754565b63ffffffff8c166000818152606b6020526040908190208d9055518c91907f0762b282466177911d330a0c27e7de4e70f0c930671f2080b7cf2dcb3b100f95906137f09085815260200190565b60405180910390a3505050505050505050505050565b63ffffffff82166000908152606660209081526040808320815161010080820184528254808352600184015495830195909552600283015493820193909352600382015460608201526004820154608082015260059091015460ff811660a08301526001600160601b03928104831660c0830152600160681b900490911660e08201529083101561389b57600091505061137d565b63ffffffff84166000908152606b602052604081205490816138be5782516138c8565b6138c8868361297c565b90508085106138fb5760608301516138e0828761567f565b6138ea9190615ab1565b6138f49083615667565b93506139c0565b8161390c576000935050505061137d565b606083015161391b908261567f565b8510613950578193505b61392f868561297c565b851015613948578361394081615ac5565b945050613925565b50505061137d565b6000825b61395f60018261567f565b8210156139b057600060016139748385615667565b61397f906001615667565b901c905061398d898261297c565b88101561399c578091506139aa565b6139a7816001615667565b92505b50613954565b6139bb60018261567f565b955050505b50505092915050565b6000826001600160601b0316846001600160601b031610156139ed57506000613a13565b6001600160601b0380831663ffffffff871602908516811015613a0e578094505b508390505b949350505050565b63ffffffff81166000908152606c602090815260408083206001600160a01b03861684528252808320805460ff19166001179055606a9091528120600201805460ff1691613a6883615a4c565b825460ff9182166101009390930a92830291909202199091161790555063ffffffff1660009081526068602090815260408220805460018101825590835291200180546001600160a01b039092166001600160a01b0319909216919091179055565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b4281608001511015613b845760405162461bcd60e51b815260206004820152603e6024820152600080516020615b4783398151915260448201527f6f663a206f70657261746f72207369676e6174757265206578706972656400006064820152608401610918565b6001600160a01b03821660009081527f51615ea63289f14fdd891b383e2929b2f73c675cf292e602b5fceb059f7a470060208181526040808420606086015185529091529091205460ff1615613c295760405162461bcd60e51b81526020600482015260366024820152600080516020615b478339815191526044820152751bd98e881cd85b1d08185b1c9958591e481cdc195b9d60521b6064820152608401610918565b6001600160a01b038316600090815260208281526040808320606086015184528252808320805460ff191660011790558051808201909152828152908101829052905b835151811015613d1057613cfc604051806040016040528086600001518481518110613c9a57613c9a6155a1565b6020026020010151600060028110613cb457613cb46155a1565b6020020151815260200186600001518481518110613cd457613cd46155a1565b6020026020010151600160028110613cee57613cee6155a1565b6020020151905283906147a5565b915080613d08816155cd565b915050613c6c565b50600060405180604001604052808560200151600060028110613d3557613d356155a1565b602002015181526020018560200151600160028110613d5657613d566155a1565b602002015190529050600080613da4613d91604080518082018252600080825260209182015281518083019092526001825260029082015290565b8486613d9b614848565b6201d4c0614908565b91509150818015613db25750805b613e085760405162461bcd60e51b81526020600482015260336024820152600080516020615b478339815191526044820152726f663a20696e76616c696420424c53206b657960681b6064820152608401610918565b600060405180604001604052808860400151600060028110613e2c57613e2c6155a1565b602002015181526020018860400151600160028110613e4d57613e4d6155a1565b602002015181525090506000613e74613e6f8a8a606001518b608001516120ab565b614b2c565b9050613e8d82613e82614848565b83886201d4c0614908565b9094509250838015613e9c5750825b6110995760405162461bcd60e51b81526020600482015260396024820152600080516020615b4783398151915260448201527f6f663a20696e76616c696420424c53207369676e6174757265000000000000006064820152608401610918565b815160005b81811015610e655782518451859083908110613f1f57613f1f6155a1565b6020026020010151600060028110613f3957613f396155a1565b6020020151141580613f8257508260016020020151848281518110613f6057613f606155a1565b6020026020010151600160028110613f7a57613f7a6155a1565b602002015114155b613fc55760405162461bcd60e51b81526020600482015260146024820152734475706c69636174656420426c735075624b657960601b6044820152606401610918565b80613fcf816155cd565b915050613f01565b63ffffffff8216600090815260686020526040812054905b8181101561413b5763ffffffff8416600090815260686020526040902080546001600160a01b03851691908390811061402a5761402a6155a1565b6000918252602090912001546001600160a01b031614156141295763ffffffff8416600090815260686020526040902061406560018461567f565b81548110614075576140756155a1565b600091825260208083209091015463ffffffff871683526068909152604090912080546001600160a01b0390921691839081106140b4576140b46155a1565b600091825260208083209190910180546001600160a01b0319166001600160a01b03949094169390931790925563ffffffff8616815260689091526040902080548061410257614102615adc565b600082815260209020810160001990810180546001600160a01b031916905501905561413b565b80614133816155cd565b915050613fef565b5063ffffffff831660009081526068602052604090205461415d906001615667565b81146111745760405162461bcd60e51b815260206004820152602960248201527f4f70657261746f7220646f65736e277420657869737420696e20636f6d6d69746044820152683a32b2a0b23239399760b91b6064820152608401610918565b604051600160f91b6020820152602181018390526041810182905260009060610160405160208183030381529060405280519060200120905092915050565b604051806101000160405280438152602001600081526020018781526020018681526020018581526020018460ff168152602001836001600160601b03168152602001826001600160601b0316815250606660008963ffffffff1663ffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548160ff021916908360ff16021790555060c08201518160050160016101000a8154816001600160601b0302191690836001600160601b0316021790555060e082015181600501600d6101000a8154816001600160601b0302191690836001600160601b0316021790555090505060405180606001604052806000801b815260200160006001600160e01b03168152602001600063ffffffff16815250606760008963ffffffff1663ffffffff16815260200190815260200160002060008081526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160e01b0302191690836001600160e01b03160217905550604082015181600101601c6101000a81548163ffffffff021916908363ffffffff16021790555090505060658790806001815401808255809150506001900390600052602060002090600891828204019190066004029091909190916101000a81548163ffffffff021916908363ffffffff1602179055508260ff168763ffffffff167f443f7a0c0eb557351b38f3fed112889e529704fb0ccaac63b1f0914816d880f38888888787604051614495959493929190948552602085019390935260408401919091526001600160601b03908116606084015216608082015260a00190565b60405180910390a350505050505050565b6144b08282613b1c565b6001600160a01b0382166000908152606a6020526040902060018101546145195760405162461bcd60e51b815260206004820152601b60248201527f4f70657261746f72206973206e6f7420726567697374657265642e00000000006044820152606401610918565b600181015482515160005b818110156145ff576145a384600101805480602002602001604051908101604052809291908181526020016000905b82821015612ea75760008481526020902060408051808201918290529160028581029091019182845b81548152602001906001019080831161457c57505050505081526020019060010190614553565b83600101856000015182815181106145bd576145bd6155a1565b60209081029190910181015182546001810184556000938452919092206145ec92600292830290910191614e8a565b50806145f7816155cd565b915050614524565b5060408051838152602081018390526000918101919091526001600160a01b03861690600080516020615b2783398151915290606001611f1c565b6000826001600160601b0316846001600160601b0316101561465e5750600061215b565b6000826001600160601b0316600186036001600160601b03168161468457614684615a9b565b04600101905063ffffffff8016816001600160601b031611156146d45760405162461bcd60e51b81526020600482015260086024820152674f766572466c6f7760c01b6044820152606401610918565b905061215b565b8151602080840151604051600160f81b9281019290925260218201929092526041810191909152606084901b6bffffffffffffffffffffffff1916606182015260a082901b6001600160a01b03191660758201526000906081016040516020818303038152906040528051906020012090509392505050565b61475d81614bbc565b63ffffffff9390931660009081526067602090815260408083209483529390529190912060010180546001600160e01b0319166001600160e01b039093169290921790915550565b60408051808201909152600080825260208201526147c1614eb8565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa905080801561480057614802565bfe5b50806148405760405162461bcd60e51b815260206004820152600d60248201526c1958cb5859190b59985a5b1959609a1b6044820152606401610918565b505092915050565b614850614ed6565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec82527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d60208381019190915281019190915290565b60408051808201825286815260208082018690528251808401909352868352820184905260009182919061493a614efb565b60005b6002811015614aff576000614953826006615696565b9050848260028110614967576149676155a1565b60200201515183614979836000615667565b600c8110614989576149896155a1565b60200201528482600281106149a0576149a06155a1565b602002015160200151838260016149b79190615667565b600c81106149c7576149c76155a1565b60200201528382600281106149de576149de6155a1565b60200201515151836149f1836002615667565b600c8110614a0157614a016155a1565b6020020152838260028110614a1857614a186155a1565b6020020151516001602002015183614a31836003615667565b600c8110614a4157614a416155a1565b6020020152838260028110614a5857614a586155a1565b602002015160200151600060028110614a7357614a736155a1565b602002015183614a84836004615667565b600c8110614a9457614a946155a1565b6020020152838260028110614aab57614aab6155a1565b602002015160200151600160028110614ac657614ac66155a1565b602002015183614ad7836005615667565b600c8110614ae757614ae76155a1565b60200201525080614af7816155cd565b91505061493d565b50614b08614f1a565b60006020826101808560088cfa9151919c9115159b50909950505050505050505050565b604080518082019091526000808252602082015260008080614b5c600080516020615b0783398151915286615af2565b90505b614b6881614c29565b9093509150600080516020615b07833981519152828309831415614ba2576040805180820190915290815260208101919091529392505050565b600080516020615b07833981519152600182089050614b5f565b60006001600160e01b03821115614c255760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610918565b5090565b60008080600080516020615b078339815191526003600080516020615b0783398151915286600080516020615b07833981519152888909090890506000614c9f827f0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52600080516020615b07833981519152614cab565b91959194509092505050565b600080614cb6614f1a565b614cbe614f38565b602080825281810181905260408201819052606082018890526080820187905260a082018690528260c08360056107d05a03fa9250828015614800575082614d485760405162461bcd60e51b815260206004820152601a60248201527f424e3235342e6578704d6f643a2063616c6c206661696c7572650000000000006044820152606401610918565b505195945050505050565b60405180604001604052806002906020820280368337509192915050565b828054828255906000526020600020906002028101928215614dbb579160200282015b82811115614dbb578251614dab9083906002614e8a565b5091602001919060020190614d94565b50614c25929150614f56565b8260028101928215614df5579160200282015b82811115614df5578235825591602001919060010190614dda565b50614c25929150614f70565b50805460008255600202906000526020600020908101906126419190614f56565b50805460008255600202906000526020600020908101906126419190614f85565b828054828255906000526020600020906002028101928215614dbb579160400282015b82811115614dbb57614e7a82846002614dc7565b5091604001919060020190614e66565b8260028101928215614df5579160200282015b82811115614df5578251825591602001919060010190614e9d565b60405180608001604052806004906020820280368337509192915050565b6040518060400160405280614ee9614d53565b8152602001614ef6614d53565b905290565b604051806101800160405280600c906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b80821115614c255760008082556001820155600201614f56565b5b80821115614c255760008155600101614f71565b5b80821115614c2557805463ffffffff1916815560006001820155600201614f86565b600060208284031215614fba57600080fd5b5035919050565b6001600160a01b038116811461264157600080fd5b60008083601f840112614fe857600080fd5b5081356001600160401b03811115614fff57600080fd5b6020830191508360208260051b850101111561501a57600080fd5b9250929050565b60008060006040848603121561503657600080fd5b833561504181614fc1565b925060208401356001600160401b0381111561505c57600080fd5b61506886828701614fd6565b9497909650939450505050565b803563ffffffff8116811461508957600080fd5b919050565b600080604083850312156150a157600080fd5b82356150ac81614fc1565b91506150ba60208401615075565b90509250929050565b600080604083850312156150d657600080fd5b6150df83615075565b946020939093013593505050565b803560ff8116811461508957600080fd5b6001600160601b038116811461264157600080fd5b600080600080600080600080610100898b03121561513057600080fd5b61513989615075565b97506020890135965060408901359550606089013594506080890135935061516360a08a016150ed565b925060c0890135615173816150fe565b915060e0890135615183816150fe565b809150509295985092959890939650565b600061012082840312156151a757600080fd5b50919050565b6000806000606084860312156151c257600080fd5b83356151cd81614fc1565b925060208401356151dd81614fc1565b915060408401356001600160401b038111156151f857600080fd5b61520486828701615194565b9150509250925092565b60006020828403121561522057600080fd5b813561215b81614fc1565b6020808252825182820181905260009190848201906040850190845b818110156130fd5783516001600160601b031683529284019291840191600101615247565b6000806040838503121561527f57600080fd5b823561528a81614fc1565b9150602083013561529a81614fc1565b809150509250929050565b600080604083850312156152b857600080fd5b82356150df81614fc1565b6000602082840312156152d557600080fd5b61215b82615075565b600080604083850312156152f157600080fd5b61528a83615075565b6020808252825182820181905260009190848201906040850190845b818110156130fd5783516001600160a01b031683529284019291840191600101615316565b60008060006060848603121561535057600080fd5b833561535b81614fc1565b92506151dd60208501615075565b60008060006040848603121561537e57600080fd5b83356001600160401b0381111561539457600080fd5b6153a086828701614fd6565b90945092506153b3905060208501615075565b90509250925092565b6000806000606084860312156153d157600080fd5b83356153dc81614fc1565b95602085013595506040909401359392505050565b60208082528251828201819052600091906040908185019086840185805b8381101561544c57825185835b60028110156154395782518252918901919089019060010161541c565b505050938501939186019160010161540f565b509298975050505050505050565b60006020828403121561546c57600080fd5b81356001600160401b0381111561548257600080fd5b613a1384828501615194565b600080600080600080600060e0888a0312156154a957600080fd5b6154b288615075565b96506020880135955060408801359450606088013593506154d5608089016150ed565b925060a08801356154e5816150fe565b915060c08801356154f5816150fe565b8091505092959891949750929550565b6000806040838503121561551857600080fd5b823561552381614fc1565b915060208301356001600160401b0381111561553e57600080fd5b61554a85828601615194565b9150509250929050565b6020808252602d908201527f4f6e6c79204c616772616e676520736572766963652063616e2063616c6c207460408201526c3434b990333ab731ba34b7b71760991b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156155e1576155e16155b7565b5060010190565b600063ffffffff80831681811415615602576156026155b7565b6001019392505050565b634e487b7160e01b600052604160045260246000fd5b60208082526025908201527f5468652064656469636174656420636861696e206973206e6f742073756273636040820152641c9a58995960da1b606082015260800190565b6000821982111561567a5761567a6155b7565b500190565b600082821015615691576156916155b7565b500390565b60008160001904831182151516156156b0576156b06155b7565b500290565b6000808335601e198436030181126156cc57600080fd5b8301803591506001600160401b038211156156e657600080fd5b6020019150600681901b360382131561501a57600080fd5b60405160a081016001600160401b03811182821017156157205761572061560c565b60405290565b604080519081016001600160401b03811182821017156157205761572061560c565b604051601f8201601f191681016001600160401b03811182821017156157705761577061560c565b604052919050565b60006001600160401b038211156157915761579161560c565b5060051b60200190565b600082601f8301126157ac57600080fd5b6157b4615726565b8060408401858111156157c657600080fd5b845b818110156157e05780358452602093840193016157c8565b509095945050505050565b600082601f8301126157fc57600080fd5b615804615726565b80608084018581111561581657600080fd5b845b818110156157e05761582a878261579b565b8452602090930192604001615818565b6000610120823603121561584d57600080fd5b6158556156fe565b82356001600160401b0381111561586b57600080fd5b830136601f82011261587c57600080fd5b8035602061589161588c83615778565b615748565b82815260069290921b830181019181810190368411156158b057600080fd5b938201935b838510156158d9576158c7368661579b565b825282820191506040850194506158b5565b8552506158e8368783016157eb565b818501525050506158fc3660a0850161579b565b604082015260e083013560608201526101009092013560808301525090565b6020808252825182820181905260009190848201906040850190845b818110156130fd57835160ff1683529284019291840191600101615937565b6000602080838503121561596957600080fd5b82516001600160401b0381111561597f57600080fd5b8301601f8101851361599057600080fd5b805161599e61588c82615778565b81815260059190911b820183019083810190878311156159bd57600080fd5b928401925b828410156159e45783516159d581614fc1565b825292840192908401906159c2565b979650505050505050565b600060208284031215615a0157600080fd5b815161215b816150fe565b600060ff821680615a1f57615a1f6155b7565b6000190192915050565b600060ff821660ff841680821015615a4357615a436155b7565b90039392505050565b600060ff821660ff811415615a6357615a636155b7565b60010192915050565b60006001600160601b0380831681851681830481118215151615615a9257615a926155b7565b02949350505050565b634e487b7160e01b600052601260045260246000fd5b600082615ac057615ac0615a9b565b500490565b600081615ad457615ad46155b7565b506000190190565b634e487b7160e01b600052603160045260246000fd5b600082615b0157615b01615a9b565b50069056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47ded05fe36328e698032818f06b33ec59b066b9f59547700fa2bc365517f7f9a1424c534b6579436865636b65722e636865636b424c534b65795769746850726fa2646970667358221220c833c93e284de6dbca6bf208b651b7e267fea6fb52e11199bc7799286a3ee74164736f6c634300080c003300000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f000000000000000000000000747dc3f9fe7df7a18dd79f6f40b3a1ed85aa75e8
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102745760003560e01c80637285645511610151578063ac8a584a116100c3578063cfedf42711610087578063cfedf427146107d6578063d598d4c9146107e9578063def9e7d514610810578063ef03067314610854578063f2fde38b1461087b578063f698da251461088e57600080fd5b8063ac8a584a14610777578063bf988ab61461078a578063c4d66de81461079d578063c5f7c4e9146107b0578063c8491506146107c357600080fd5b8063935a9b6a11610115578063935a9b6a1461065457806395703d08146106675780639e224428146106be578063a43dd8dd146106d1578063a63490a2146106f1578063a6b150681461076457600080fd5b8063728564551461054c57806378d81d08146105f6578063829c7dd71461060957806385ab9a7a1461061c5780638da5cb5b1461062f57600080fd5b80633811db0d116101ea57806353b7a0ff116101ae57806353b7a0ff146104ad57806356bf7c25146104db5780635af1a88f146104fb5780636b11c38e14610526578063715018a614610539578063727cb30f1461054157600080fd5b80633811db0d146103db57806338fa59d1146104435780633bc72805146104675780633d6a26791461047a5780634db6f74a1461048d57600080fd5b806316c72b2f1161023c57806316c72b2f1461030f57806319a74c5f146103225780631de8d88e1461034c57806320606b701461038157806324ca7a48146103a85780632c36c718146103c857600080fd5b806309d23e24146102795780630c57b9d4146102a65780630e9f564b146102bb5780630f225b84146102ce57806313538c7f146102fc575b600080fd5b61028c610287366004614fa8565b610896565b60405163ffffffff90911681526020015b60405180910390f35b6102b96102b4366004615021565b6108d0565b005b6102b96102c936600461508e565b610d6b565b6102e16102dc3660046150c3565b610e6b565b6040805193845260208401929092529082015260600161029d565b6102b961030a366004615113565b611011565b6102b961031d3660046151ad565b6110a4565b61033561033036600461520e565b611179565b60408051921515835260208301919091520161029d565b6103737f1a3843f7e4c22d9c427c97a0094da0bc4b96584c20d784e647bac3bdf2f8e5a081565b60405190815260200161029d565b6103737f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6103bb6103b636600461508e565b61132a565b60405161029d919061522b565b6102b96103d636600461526c565b611383565b6104336103e93660046152a5565b6001600160a01b039190911660009081527f51615ea63289f14fdd891b383e2929b2f73c675cf292e602b5fceb059f7a470060209081526040808320938352929052205460ff1690565b604051901515815260200161029d565b61044e600160f81b81565b6040516001600160f81b0319909116815260200161029d565b6102b96104753660046150c3565b61148a565b6103356104883660046152c3565b611499565b61037361049b3660046152c3565b606b6020526000908152604090205481565b6104336104bb3660046152de565b606c60209081526000928352604080842090915290825290205460ff1681565b6104ee6104e936600461520e565b6114c9565b60405161029d91906152fa565b61050e61050936600461508e565b61169e565b6040516001600160601b03909116815260200161029d565b6102b961053436600461508e565b6117e5565b6102b9611c59565b61044e600160f91b81565b6105ac61055a3660046152c3565b606660205260009081526040902080546001820154600283015460038401546004850154600590950154939492939192909160ff8116906001600160601b036101008204811691600160681b90041688565b604080519889526020890197909752958701949094526060860192909252608085015260ff1660a08401526001600160601b0390811660c08401521660e08201526101000161029d565b6103736106043660046150c3565b611c6d565b6102b961061736600461533b565b611caf565b61043361062a3660046150c3565b611f2b565b6033546001600160a01b03165b6040516001600160a01b03909116815260200161029d565b6102b9610662366004615369565b611f49565b61069d61067536600461520e565b606a60205260009081526040902080546002909101546001600160a01b039091169060ff1682565b604080516001600160a01b03909316835260ff90911660208301520161029d565b6103736106cc3660046153bc565b6120ab565b6106e46106df36600461520e565b612162565b60405161029d91906153f1565b61073b6106ff3660046150c3565b6067602090815260009283526040808420909152908252902080546001909101546001600160e01b03811690600160e01b900463ffffffff1683565b604080519384526001600160e01b03909216602084015263ffffffff169082015260600161029d565b6102b96107723660046150c3565b6121f8565b6102b961078536600461520e565b6122c2565b61063c6107983660046150c3565b612358565b6102b96107ab36600461520e565b612390565b6102b96107be36600461545a565b612528565b6102b96107d136600461548e565b612644565b6102b96107e4366004615505565b6126e2565b61063c7f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f81565b61082361081e3660046150c3565b612749565b60408051825181526020808401516001600160e01b0316908201529181015163ffffffff169082015260600161029d565b61063c7f000000000000000000000000747dc3f9fe7df7a18dd79f6f40b3a1ed85aa75e881565b6102b961088936600461520e565b6127cd565b610373612843565b606581815481106108a657600080fd5b9060005260206000209060089182820401919006600402915054906101000a900463ffffffff1681565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f16146109215760405162461bcd60e51b815260040161091890615554565b60405180910390fd5b6001600160a01b0383166000908152606a6020908152604080832060010180548251818502810185019093528083529192909190849084015b828210156109aa5760008481526020902060408051808201918290529160028581029091019182845b8154815260200190600101908083116109835750505050508152602001906001019061095a565b505082519293505050828111610a1c5760405162461bcd60e51b815260206004820152603160248201527f496e76616c696420696e6469636573206c656e6774682c20424c53206b6579736044820152701031b0b73737ba1031329032b6b83a3c9760791b6064820152608401610918565b60005b83811015610b6257848482818110610a3957610a396155a1565b9050602002016020810190610a4e91906152c3565b63ffffffff168211610a925760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610918565b600083868684818110610aa757610aa76155a1565b9050602002016020810190610abc91906152c3565b63ffffffff1681518110610ad257610ad26155a1565b6020026020010151600060028110610aec57610aec6155a1565b6020020152600083868684818110610b0657610b066155a1565b9050602002016020810190610b1b91906152c3565b63ffffffff1681518110610b3157610b316155a1565b6020026020010151600160028110610b4b57610b4b6155a1565b602002015280610b5a816155cd565b915050610a1f565b506000805b82811015610c3f57838181518110610b8157610b816155a1565b6020026020010151600060028110610b9b57610b9b6155a1565b6020020151151580610bdc5750838181518110610bba57610bba6155a1565b6020026020010151600160028110610bd457610bd46155a1565b602002015115155b15610c2d57838181518110610bf357610bf36155a1565b6020026020010151848363ffffffff1681518110610c1357610c136155a1565b60200260200101819052508180610c29906155e8565b9250505b80610c37816155cd565b915050610b67565b5060008163ffffffff166001600160401b03811115610c6057610c6061560c565b604051908082528060200260200182016040528015610c9957816020015b610c86614d53565b815260200190600190039081610c7e5790505b50905060005b8263ffffffff16811015610cf757848181518110610cbf57610cbf6155a1565b6020026020010151828281518110610cd957610cd96155a1565b60200260200101819052508080610cef906155cd565b915050610c9f565b506001600160a01b0387166000908152606a602090815260409091208251610d2792600190920191840190614d71565b5060408051848152600060208201529081018690526001600160a01b03881690600080516020615b278339815191529060600160405180910390a250505050505050565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f1614610db35760405162461bcd60e51b815260040161091890615554565b63ffffffff81166000908152606c602090815260408083206001600160a01b038616845290915290205460ff16610dfc5760405162461bcd60e51b815260040161091890615622565b600080610e0883611499565b915091508115610e5a5760405162461bcd60e51b815260206004820152601e60248201527f5468652064656469636174656420636861696e206973206c6f636b65642e00006044820152606401610918565b610e658484836128c2565b50505050565b63ffffffff821660008181526066602090815260408083208151610100808201845282548252600183015482860152600283015482850152600383015460608301526004830154608083015260059092015460ff811660a08301526001600160601b03928104831660c0830152600160681b900490911660e0820152938352606b9091528120549091829182919085610f4457815194508015610f1857610f1387600161297c565b610f29565b60608201518251610f299190615667565b9250816080015183610f3b919061567f565b9350505061100a565b808611610f9f57610f55878761297c565b9450858114610f7757610f7287610f6d886001615667565b61297c565b610f86565b6060820151610f869086615667565b9250816080015183610f98919061567f565b9350611007565b6000808211610faf578251610fb9565b610fb9888361297c565b6060840151909150610fcb838961567f565b610fd59190615696565b610fdf9082615667565b9550826060015186610ff19190615667565b9350826080015184611003919061567f565b9450505b50505b9250925092565b6110196129ad565b63ffffffff8816600090815260666020526040902054806110745760405162461bcd60e51b815260206004820152601560248201527410da185a5b881b9bdd081a5b9a5d1a585b1a5e9959605a1b6044820152606401610918565b61107e8383612a07565b6110888686612a81565b6110998989838a8a8a8a8a8a612ad0565b505050505050505050565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f16146110ec5760405162461bcd60e51b815260040161091890615554565b6111616110f982806156b5565b808060200260200160405190810160405280939291908181526020016000905b828210156111575760408051808201825290808402870190600290839083908082843760009201919091525050508152600190910190602001611119565b5050505050612c74565b611174838361116f8461583a565b612d94565b505050565b6001600160a01b038082166000908152606a602090815260408083208151608081018352815490951685526001810180548351818602810186019094528084529495869586959194858301939092909190879084015b8282101561121f5760008481526020902060408051808201918290529160028581029091019182845b8154815260200190600101908083116111f8575050505050815260200190600101906111cf565b50505090825250600282015460ff16602080830191909152600383018054604080518285028101850182528281529401939260009084015b8282101561129c5760008481526020908190206040805180820190915260028502909101805463ffffffff168252600190810154828401529083529092019101611257565b50505091525050604081015190915060ff16156112bf5750600093849350915050565b606081015151600090815b8181101561131b576000846060015182815181106112ea576112ea6155a1565b60200260200101519050838160200151111561130857806020015193505b5080611313816155cd565b9150506112ca565b50600196919550909350505050565b60606000611338848461169e565b63ffffffff84166000908152606660205260409020600501549091506001600160601b036101008204811691600160681b900416611377838383612f6d565b93505050505b92915050565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f16146113cb5760405162461bcd60e51b815260040161091890615554565b6001600160a01b0382166000908152606a60205260409020600101546114335760405162461bcd60e51b815260206004820152601b60248201527f4f70657261746f72206973206e6f7420726567697374657265642e00000000006044820152606401610918565b6001600160a01b038281166000818152606a602052604080822080546001600160a01b0319169486169485179055517ff29351472086a2d8b1af521f96d65142d14518260a62923a07aa7c9e3c752d849190a35050565b611495828243613109565b5050565b60008060006114a88443613806565b90506000806114b78684610e6b565b43919091119890975095505050505050565b6065546001600160a01b0382166000908152606a6020526040812060020154606092919060ff166001600160401b038111156115075761150761560c565b604051908082528060200260200182016040528015611530578160200160208202803683370190505b5090506000805b8381101561160357600060658281548110611554576115546155a1565b6000918252602080832060088304015460079092166004026101000a90910463ffffffff16808352606c825260408084206001600160a01b038c16855290925291205490915060ff16156115f05763ffffffff811660009081526066602052604090206005015460ff1684846115c9816155cd565b9550815181106115db576115db6155a1565b602002602001019060ff16908160ff16815250505b50806115fb816155cd565b915050611537565b50604051635ce8f06760e01b81526001600160a01b037f000000000000000000000000747dc3f9fe7df7a18dd79f6f40b3a1ed85aa75e81690635ce8f0679061165090859060040161591b565b600060405180830381865afa15801561166d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116959190810190615956565b95945050505050565b63ffffffff81166000908152606660209081526040808320815161010080820184528254825260018301548286015260028301548285015260038301546060830152600480840154608084015260059093015460ff811660a084018190529181046001600160601b0390811660c0850152600160681b9091041660e08301528351631b48130b60e31b8152928301526001600160a01b0387811660248401529251909385937f000000000000000000000000747dc3f9fe7df7a18dd79f6f40b3a1ed85aa75e8169263da40985892604480830193928290030181865afa15801561178c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b091906159ef565b6001600160a01b0386166000908152606a602052604090206001015460c084015160e0850151929350611695928491906139c9565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f161461182d5760405162461bcd60e51b815260040161091890615554565b63ffffffff811660009081526066602052604090205461189e5760405162461bcd60e51b815260206004820152602660248201527f5468652064656469636174656420636861696e206973206e6f742072656769736044820152653a32b932b21760d11b6064820152608401610918565b60006118a982611499565b50905080156118fa5760405162461bcd60e51b815260206004820152601e60248201527f5468652064656469636174656420636861696e206973206c6f636b65642e00006044820152606401610918565b6001600160a01b0383166000908152606a6020908152604080832060030180548251818502810185019093528083529192909190849084015b828210156119785760008481526020908190206040805180820190915260028502909101805463ffffffff168252600190810154828401529083529092019101611933565b5050825192935060009150505b81811015611a3d5760008382815181106119a1576119a16155a1565b602002602001015190508563ffffffff16816000015163ffffffff161415611a2a5743816020015110611a2a5760405162461bcd60e51b815260206004820152602b60248201527f5468652064656463696174656420636861696e206973207768696c6520756e7360448201526a3ab139b1b934b134b7339760a91b6064820152608401610918565b5080611a35816155cd565b915050611985565b5063ffffffff84166000908152606c602090815260408083206001600160a01b038916845290915290205460ff1615611acb5760405162461bcd60e51b815260206004820152602a60248201527f5468652064656469636174656420636861696e20697320616c726561647920736044820152693ab139b1b934b132b21760b11b6064820152608401610918565b63ffffffff84166000908152606660209081526040808320815161010080820184528254825260018301548286015260028301548285015260038301546060830152600480840154608084015260059093015460ff811660a084018190529181046001600160601b0390811660c0850152600160681b9091041660e08301528351631b48130b60e31b8152928301526001600160a01b038a8116602484015292519094937f000000000000000000000000747dc3f9fe7df7a18dd79f6f40b3a1ed85aa75e89093169263da40985892604480820193918290030181865afa158015611bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bde91906159ef565b90508160c001516001600160601b0316816001600160601b03161015611c465760405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e7420566f74652057656967687400000000000000006044820152606401610918565b611c508787613a1b565b50505050505050565b611c616129ad565b611c6b6000613aca565b565b6000611c798383613806565b905080158015611ca1575063ffffffff83166000908152606660205260409020600201548210155b1561137d5750600192915050565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f1614611cf75760405162461bcd60e51b815260040161091890615554565b611d0983611d048361583a565b613b1c565b611d1381806156b5565b9050600114611d645760405162461bcd60e51b815260206004820152601d60248201527f4c656e6774682073686f756c64206265203120666f72207570646174650000006044820152606401610918565b6001600160a01b0383166000908152606a60205260409020600101805463ffffffff84168111611dc65760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610918565b611e9082805480602002602001604051908101604052809291908181526020016000905b82821015611e3a5760008481526020902060408051808201918290529160028581029091019182845b815481526020019060010190808311611e1357505050505081526020019060010190611dea565b50611e4b92508791508190506156b5565b6000818110611e5c57611e5c6155a1565b9050604002016002806020026040519081016040528092919082600260200280828437600092019190915250613efc915050565b611e9a83806156b5565b6000818110611eab57611eab6155a1565b905060400201828563ffffffff1681548110611ec957611ec96155a1565b9060005260206000209060020201906002611ee5929190614dc7565b5060408051828152600160208201819052918101919091526001600160a01b03861690600080516020615b27833981519152906060015b60405180910390a25050505050565b600080611f3d846102dc60018661567f565b50431195945050505050565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f1614611f915760405162461bcd60e51b815260040161091890615554565b8160005b818110156120a4576000858583818110611fb157611fb16155a1565b9050602002016020810190611fc6919061520e565b63ffffffff85166000908152606c602090815260408083206001600160a01b038516845290915290205490915060ff166120125760405162461bcd60e51b815260040161091890615622565b63ffffffff84166000908152606c602090815260408083206001600160a01b03851684529091529020805460ff1916905561204d8482613fd7565b6001600160a01b0381166000908152606a60205260408120600201805460ff169161207783615a0c565b91906101000a81548160ff021916908360ff1602179055505050808061209c906155cd565b915050611f95565b5050505050565b604080517f1a3843f7e4c22d9c427c97a0094da0bc4b96584c20d784e647bac3bdf2f8e5a060208201526001600160a01b038516918101919091526060810183905260808101829052600090819060a001604051602081830303815290604052805190602001209050600061211e612843565b60405161190160f01b602082015260228101919091526042810183905260620160408051601f198184030181529190528051602090910120925050505b9392505050565b6001600160a01b0381166000908152606a60209081526040808320600101805482518185028101850190935280835260609492939192909184015b828210156121ed5760008481526020902060408051808201918290529160028581029091019182845b8154815260200190600101908083116121c65750505050508152602001906001019061219d565b505050509050919050565b6122006129ad565b63ffffffff82166000908152606b6020526040902054811461226f5760405162461bcd60e51b815260206004820152602260248201527f5468652065706f63684e756d626572206973206e6f7420746865206c617465736044820152613a1760f11b6064820152608401610918565b63ffffffff8216600090815260676020908152604080832084845290915281208181556001908101919091556122a5908261567f565b63ffffffff9092166000908152606b602052604090209190915550565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f161461230a5760405162461bcd60e51b815260040161091890615554565b6001600160a01b0381166000908152606a6020526040812080546001600160a01b03191681559061233e6001830182614e01565b60028201805460ff19169055611174600383016000614e22565b6068602052816000526040600020818154811061237457600080fd5b6000918252602090912001546001600160a01b03169150829050565b600054610100900460ff16158080156123b05750600054600160ff909116105b806123ca5750303b1580156123ca575060005460ff166001145b61242d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610918565b6000805460ff191660011790558015612450576000805461ff0019166101001790555b60015b60148160ff16116124d5576124b060696000612470600185615a29565b60ff1660ff16815260200190815260200160002054606960006001856124969190615a29565b60ff1660ff168152602001908152602001600020546141bd565b60ff8216600090815260696020526040902055806124cd81615a4c565b915050612453565b506124df82613aca565b8015611495576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6125306129ad565b61253a81806156b5565b905060011461258b5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f6e65206b65792073686f756c642062652070726f76696465642e6044820152606401610918565b61259830611d048361583a565b6125a281806156b5565b306000908152606a602052604090206125c092600190910191614e43565b50306000908152606a60205260409020600101546126105760408051600080825260016020830152918101919091523090600080516020615b27833981519152906060015b60405180910390a250565b60408051600180825260208201819052918101919091523090600080516020615b2783398151915290606001612605565b50565b61264c6129ad565b63ffffffff8716600090815260666020526040902054156126bf5760405162461bcd60e51b815260206004820152602760248201527f436f6d6d69747465652068617320616c7265616479206265656e20696e69746960448201526630b634bd32b21760c91b6064820152608401610918565b6126c98282612a07565b6126d38585612a81565b611c50878787878787876141fc565b336001600160a01b037f00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f161461272a5760405162461bcd60e51b815260040161091890615554565b6127376110f982806156b5565b611495826127448361583a565b6144a6565b60408051606081018252600080825260208201819052918101829052906127708484611c6d565b63ffffffff9485166000908152606760209081526040808320938352928152908290208251606081018452815481526001909101546001600160e01b03811692820192909252600160e01b90910490951690850152509192915050565b6127d56129ad565b6001600160a01b03811661283a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610918565b61264181613aca565b604080517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86660208201527fa1cdac95fbc855fc66c2df41a0f389eb0dff513790ade024e7ad056efd60a6f49181019190915246606082015230608082015260009060a00160405160208183030381529060405280519060200120905090565b63ffffffff8281166000818152606c602090815260408083206001600160a01b03891684528252808320805460ff19169055606a825280832081518083019092529381528082018681526003850180546001818101835591865293852092516002948502909301805463ffffffff191693909716929092178655519401939093559181018054919260ff9092169161295983615a0c565b91906101000a81548160ff021916908360ff16021790555050610e658385613fd7565b63ffffffff91909116600090815260676020908152604080832093835292905220600101546001600160e01b031690565b6033546001600160a01b03163314611c6b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610918565b6000826001600160601b0316118015612a3c5750612a26826002615a6c565b6001600160601b0316816001600160601b031610155b6114955760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081b5a5b8bdb585e0815d95a59da1d60521b6044820152606401610918565b8082116114955760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420667265657a65206475726174696f6e0000000000000000006044820152606401610918565b6040518061010001604052808881526020018981526020018781526020018681526020018581526020018460ff168152602001836001600160601b03168152602001826001600160601b0316815250606660008b63ffffffff1663ffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548160ff021916908360ff16021790555060c08201518160050160016101000a8154816001600160601b0302191690836001600160601b0316021790555060e082015181600501600d6101000a8154816001600160601b0302191690836001600160601b031602179055509050508260ff168963ffffffff167fc0f5fe53277733159fe7a739f75b98e959a28a0859db2c46e04a5f4820b964008a8989898888604051612c61969594939291909586526020860194909452604085019290925260608401526001600160601b0390811660808401521660a082015260c00190565b60405180910390a3505050505050505050565b8051612cbb5760405162461bcd60e51b815260206004820152601660248201527522b6b83a3c9021262990283ab13634b19025b2bcb99760511b6044820152606401610918565b805160005b8181101561117457828181518110612cda57612cda6155a1565b6020026020010151600060028110612cf457612cf46155a1565b602002015115801590612d365750828181518110612d1457612d146155a1565b6020026020010151600160028110612d2e57612d2e6155a1565b602002015115155b612d825760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420424c53205075626c6963204b65792e0000000000000000006044820152606401610918565b80612d8c816155cd565b915050612cc0565b612d9e8382613b1c565b6001600160a01b0383166000908152606a6020526040812080546001600160a01b031916815590612dd26001830182614e01565b60028201805460ff19169055612dec600383016000614e22565b50506001600160a01b038381166000908152606a60205260408120600181015481546001600160a01b0319169386169390931781558351519092915b81811015612f2a57612ece84600101805480602002602001604051908101604052809291908181526020016000905b82821015612ea75760008481526020902060408051808201918290529160028581029091019182845b815481526020019060010190808311612e8057505050505081526020019060010190612e57565b5050505086600001518381518110612ec157612ec16155a1565b6020026020010151613efc565b8360010185600001518281518110612ee857612ee86155a1565b6020908102919091018101518254600181018455600093845291909220612f1792600292830290910191614e8a565b5080612f22816155cd565b915050612e28565b50604080518381526020810183905260008183015290516001600160a01b03881691600080516020615b27833981519152919081900360600190a2505050505050565b60606000612f7c85858561463a565b63ffffffff1690506000816001600160401b03811115612f9e57612f9e61560c565b604051908082528060200260200182016040528015612fc7578160200160208202803683370190505b50905081612fd857915061215b9050565b6000865b8686016001600160601b0316816001600160601b0316106130305785838380600101945081518110613010576130106155a1565b6001600160601b0390921660209283029190910190910152859003612fdc565b856001600160601b0316816001600160601b031611156130c35786838380600101945081518110613063576130636155a1565b60200260200101906001600160601b031690816001600160601b03168152505086810383838060010194508151811061309e5761309e6155a1565b60200260200101906001600160601b031690816001600160601b0316815250506130fd565b808383806001019450815181106130dc576130dc6155a1565b60200260200101906001600160601b031690816001600160601b0316815250505b50909695505050505050565b6131138383611f2b565b6131795760405162461bcd60e51b815260206004820152603160248201527f426c6f636b206e756d626572206973207072696f7220746f20636f6d6d69747460448201527032b290333932b2bd32903bb4b73237bb9760791b6064820152608401610918565b63ffffffff83166000908152606b6020526040902054829061319c906001615667565b146131f45760405162461bcd60e51b815260206004820152602260248201527f5468652065706f63684e756d626572206973206e6f742073657175656e746961604482015261361760f11b6064820152608401610918565b63ffffffff831660008181526066602090815260408083208151610100808201845282548252600183015482860152600283015482850152600383015460608301526004830154608083015260059092015460ff811660a083018190529281046001600160601b0390811660c08401819052600160681b9092041660e0830181905296865260688552838620805485518188028101880190965280865292979396919593949193919290918301828280156132d857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116132ba575b505083519394506001925060009150505b8281101561333b57606a6000858381518110613307576133076155a1565b6020908102919091018101516001600160a01b031682528101919091526040016000206001908101549290920191016132e9565b506000816001600160401b038111156133565761335661560c565b60405190808252806020026020018201604052801561337f578160200160208202803683370190505b50306000908152606a60205260408120600101549093509091501561342a57306000818152606a6020526040812060010180546134069392906133c4576133c46155a1565b600091825260209091206040805180820191829052926002908102909201919082845b8154815260200190600101908083116133e757505050505060006146db565b818381518110613418576134186155a1565b60209081029190910101526001909101905b60005b8381101561362d576000858281518110613449576134496155a1565b602002602001015190506000606a6000836001600160a01b03166001600160a01b031681526020019081526020016000209050600061353682600101805490507f000000000000000000000000747dc3f9fe7df7a18dd79f6f40b3a1ed85aa75e86001600160a01b031663da4098588e876040518363ffffffff1660e01b81526004016134ee92919060ff9290921682526001600160a01b0316602082015260400190565b602060405180830381865afa15801561350b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352f91906159ef565b8c8c6139c9565b90508060005b6001600160601b0382161561361c5760008c8c016001600160601b0316836001600160601b03161061356f57508a613593565b8b6001600160601b0316836001600160601b0316111561359057508b613593565b50815b80830392506135f2868660010184815481106135b1576135b16155a1565b600091825260209091206040805180820191829052926002908102909201919082845b8154815260200190600101908083116135d4575050505050836146db565b888a81518110613604576136046155a1565b6020908102919091010152506001978801970161353c565b50506001909301925061342d915050565b50600082815b600182111561372d576001828101811c905b838110156136b55761368c866001830381518110613665576136656155a1565b602002602001015187838151811061367f5761367f6155a1565b60200260200101516141bd565b86600183901c815181106136a2576136a26155a1565b6020908102919091010152600201613645565b508260011660011415613723576137018560018503815181106136da576136da6155a1565b6020026020010151606960008560ff1660ff168152602001908152602001600020546141bd565b856001830381518110613716576137166155a1565b6020026020010181815250505b9150600101613633565b5083156137525782600081518110613747576137476155a1565b602002602001015191505b5063ffffffff8c811660009081526067602090815260408083208f84529091529020600181018054928616600160e01b026001600160e01b03909316929092179091558190556137a38c8c8c614754565b63ffffffff8c166000818152606b6020526040908190208d9055518c91907f0762b282466177911d330a0c27e7de4e70f0c930671f2080b7cf2dcb3b100f95906137f09085815260200190565b60405180910390a3505050505050505050505050565b63ffffffff82166000908152606660209081526040808320815161010080820184528254808352600184015495830195909552600283015493820193909352600382015460608201526004820154608082015260059091015460ff811660a08301526001600160601b03928104831660c0830152600160681b900490911660e08201529083101561389b57600091505061137d565b63ffffffff84166000908152606b602052604081205490816138be5782516138c8565b6138c8868361297c565b90508085106138fb5760608301516138e0828761567f565b6138ea9190615ab1565b6138f49083615667565b93506139c0565b8161390c576000935050505061137d565b606083015161391b908261567f565b8510613950578193505b61392f868561297c565b851015613948578361394081615ac5565b945050613925565b50505061137d565b6000825b61395f60018261567f565b8210156139b057600060016139748385615667565b61397f906001615667565b901c905061398d898261297c565b88101561399c578091506139aa565b6139a7816001615667565b92505b50613954565b6139bb60018261567f565b955050505b50505092915050565b6000826001600160601b0316846001600160601b031610156139ed57506000613a13565b6001600160601b0380831663ffffffff871602908516811015613a0e578094505b508390505b949350505050565b63ffffffff81166000908152606c602090815260408083206001600160a01b03861684528252808320805460ff19166001179055606a9091528120600201805460ff1691613a6883615a4c565b825460ff9182166101009390930a92830291909202199091161790555063ffffffff1660009081526068602090815260408220805460018101825590835291200180546001600160a01b039092166001600160a01b0319909216919091179055565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b4281608001511015613b845760405162461bcd60e51b815260206004820152603e6024820152600080516020615b4783398151915260448201527f6f663a206f70657261746f72207369676e6174757265206578706972656400006064820152608401610918565b6001600160a01b03821660009081527f51615ea63289f14fdd891b383e2929b2f73c675cf292e602b5fceb059f7a470060208181526040808420606086015185529091529091205460ff1615613c295760405162461bcd60e51b81526020600482015260366024820152600080516020615b478339815191526044820152751bd98e881cd85b1d08185b1c9958591e481cdc195b9d60521b6064820152608401610918565b6001600160a01b038316600090815260208281526040808320606086015184528252808320805460ff191660011790558051808201909152828152908101829052905b835151811015613d1057613cfc604051806040016040528086600001518481518110613c9a57613c9a6155a1565b6020026020010151600060028110613cb457613cb46155a1565b6020020151815260200186600001518481518110613cd457613cd46155a1565b6020026020010151600160028110613cee57613cee6155a1565b6020020151905283906147a5565b915080613d08816155cd565b915050613c6c565b50600060405180604001604052808560200151600060028110613d3557613d356155a1565b602002015181526020018560200151600160028110613d5657613d566155a1565b602002015190529050600080613da4613d91604080518082018252600080825260209182015281518083019092526001825260029082015290565b8486613d9b614848565b6201d4c0614908565b91509150818015613db25750805b613e085760405162461bcd60e51b81526020600482015260336024820152600080516020615b478339815191526044820152726f663a20696e76616c696420424c53206b657960681b6064820152608401610918565b600060405180604001604052808860400151600060028110613e2c57613e2c6155a1565b602002015181526020018860400151600160028110613e4d57613e4d6155a1565b602002015181525090506000613e74613e6f8a8a606001518b608001516120ab565b614b2c565b9050613e8d82613e82614848565b83886201d4c0614908565b9094509250838015613e9c5750825b6110995760405162461bcd60e51b81526020600482015260396024820152600080516020615b4783398151915260448201527f6f663a20696e76616c696420424c53207369676e6174757265000000000000006064820152608401610918565b815160005b81811015610e655782518451859083908110613f1f57613f1f6155a1565b6020026020010151600060028110613f3957613f396155a1565b6020020151141580613f8257508260016020020151848281518110613f6057613f606155a1565b6020026020010151600160028110613f7a57613f7a6155a1565b602002015114155b613fc55760405162461bcd60e51b81526020600482015260146024820152734475706c69636174656420426c735075624b657960601b6044820152606401610918565b80613fcf816155cd565b915050613f01565b63ffffffff8216600090815260686020526040812054905b8181101561413b5763ffffffff8416600090815260686020526040902080546001600160a01b03851691908390811061402a5761402a6155a1565b6000918252602090912001546001600160a01b031614156141295763ffffffff8416600090815260686020526040902061406560018461567f565b81548110614075576140756155a1565b600091825260208083209091015463ffffffff871683526068909152604090912080546001600160a01b0390921691839081106140b4576140b46155a1565b600091825260208083209190910180546001600160a01b0319166001600160a01b03949094169390931790925563ffffffff8616815260689091526040902080548061410257614102615adc565b600082815260209020810160001990810180546001600160a01b031916905501905561413b565b80614133816155cd565b915050613fef565b5063ffffffff831660009081526068602052604090205461415d906001615667565b81146111745760405162461bcd60e51b815260206004820152602960248201527f4f70657261746f7220646f65736e277420657869737420696e20636f6d6d69746044820152683a32b2a0b23239399760b91b6064820152608401610918565b604051600160f91b6020820152602181018390526041810182905260009060610160405160208183030381529060405280519060200120905092915050565b604051806101000160405280438152602001600081526020018781526020018681526020018581526020018460ff168152602001836001600160601b03168152602001826001600160601b0316815250606660008963ffffffff1663ffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548160ff021916908360ff16021790555060c08201518160050160016101000a8154816001600160601b0302191690836001600160601b0316021790555060e082015181600501600d6101000a8154816001600160601b0302191690836001600160601b0316021790555090505060405180606001604052806000801b815260200160006001600160e01b03168152602001600063ffffffff16815250606760008963ffffffff1663ffffffff16815260200190815260200160002060008081526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160e01b0302191690836001600160e01b03160217905550604082015181600101601c6101000a81548163ffffffff021916908363ffffffff16021790555090505060658790806001815401808255809150506001900390600052602060002090600891828204019190066004029091909190916101000a81548163ffffffff021916908363ffffffff1602179055508260ff168763ffffffff167f443f7a0c0eb557351b38f3fed112889e529704fb0ccaac63b1f0914816d880f38888888787604051614495959493929190948552602085019390935260408401919091526001600160601b03908116606084015216608082015260a00190565b60405180910390a350505050505050565b6144b08282613b1c565b6001600160a01b0382166000908152606a6020526040902060018101546145195760405162461bcd60e51b815260206004820152601b60248201527f4f70657261746f72206973206e6f7420726567697374657265642e00000000006044820152606401610918565b600181015482515160005b818110156145ff576145a384600101805480602002602001604051908101604052809291908181526020016000905b82821015612ea75760008481526020902060408051808201918290529160028581029091019182845b81548152602001906001019080831161457c57505050505081526020019060010190614553565b83600101856000015182815181106145bd576145bd6155a1565b60209081029190910181015182546001810184556000938452919092206145ec92600292830290910191614e8a565b50806145f7816155cd565b915050614524565b5060408051838152602081018390526000918101919091526001600160a01b03861690600080516020615b2783398151915290606001611f1c565b6000826001600160601b0316846001600160601b0316101561465e5750600061215b565b6000826001600160601b0316600186036001600160601b03168161468457614684615a9b565b04600101905063ffffffff8016816001600160601b031611156146d45760405162461bcd60e51b81526020600482015260086024820152674f766572466c6f7760c01b6044820152606401610918565b905061215b565b8151602080840151604051600160f81b9281019290925260218201929092526041810191909152606084901b6bffffffffffffffffffffffff1916606182015260a082901b6001600160a01b03191660758201526000906081016040516020818303038152906040528051906020012090509392505050565b61475d81614bbc565b63ffffffff9390931660009081526067602090815260408083209483529390529190912060010180546001600160e01b0319166001600160e01b039093169290921790915550565b60408051808201909152600080825260208201526147c1614eb8565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa905080801561480057614802565bfe5b50806148405760405162461bcd60e51b815260206004820152600d60248201526c1958cb5859190b59985a5b1959609a1b6044820152606401610918565b505092915050565b614850614ed6565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec82527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d60208381019190915281019190915290565b60408051808201825286815260208082018690528251808401909352868352820184905260009182919061493a614efb565b60005b6002811015614aff576000614953826006615696565b9050848260028110614967576149676155a1565b60200201515183614979836000615667565b600c8110614989576149896155a1565b60200201528482600281106149a0576149a06155a1565b602002015160200151838260016149b79190615667565b600c81106149c7576149c76155a1565b60200201528382600281106149de576149de6155a1565b60200201515151836149f1836002615667565b600c8110614a0157614a016155a1565b6020020152838260028110614a1857614a186155a1565b6020020151516001602002015183614a31836003615667565b600c8110614a4157614a416155a1565b6020020152838260028110614a5857614a586155a1565b602002015160200151600060028110614a7357614a736155a1565b602002015183614a84836004615667565b600c8110614a9457614a946155a1565b6020020152838260028110614aab57614aab6155a1565b602002015160200151600160028110614ac657614ac66155a1565b602002015183614ad7836005615667565b600c8110614ae757614ae76155a1565b60200201525080614af7816155cd565b91505061493d565b50614b08614f1a565b60006020826101808560088cfa9151919c9115159b50909950505050505050505050565b604080518082019091526000808252602082015260008080614b5c600080516020615b0783398151915286615af2565b90505b614b6881614c29565b9093509150600080516020615b07833981519152828309831415614ba2576040805180820190915290815260208101919091529392505050565b600080516020615b07833981519152600182089050614b5f565b60006001600160e01b03821115614c255760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610918565b5090565b60008080600080516020615b078339815191526003600080516020615b0783398151915286600080516020615b07833981519152888909090890506000614c9f827f0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52600080516020615b07833981519152614cab565b91959194509092505050565b600080614cb6614f1a565b614cbe614f38565b602080825281810181905260408201819052606082018890526080820187905260a082018690528260c08360056107d05a03fa9250828015614800575082614d485760405162461bcd60e51b815260206004820152601a60248201527f424e3235342e6578704d6f643a2063616c6c206661696c7572650000000000006044820152606401610918565b505195945050505050565b60405180604001604052806002906020820280368337509192915050565b828054828255906000526020600020906002028101928215614dbb579160200282015b82811115614dbb578251614dab9083906002614e8a565b5091602001919060020190614d94565b50614c25929150614f56565b8260028101928215614df5579160200282015b82811115614df5578235825591602001919060010190614dda565b50614c25929150614f70565b50805460008255600202906000526020600020908101906126419190614f56565b50805460008255600202906000526020600020908101906126419190614f85565b828054828255906000526020600020906002028101928215614dbb579160400282015b82811115614dbb57614e7a82846002614dc7565b5091604001919060020190614e66565b8260028101928215614df5579160200282015b82811115614df5578251825591602001919060010190614e9d565b60405180608001604052806004906020820280368337509192915050565b6040518060400160405280614ee9614d53565b8152602001614ef6614d53565b905290565b604051806101800160405280600c906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b80821115614c255760008082556001820155600201614f56565b5b80821115614c255760008155600101614f71565b5b80821115614c2557805463ffffffff1916815560006001820155600201614f86565b600060208284031215614fba57600080fd5b5035919050565b6001600160a01b038116811461264157600080fd5b60008083601f840112614fe857600080fd5b5081356001600160401b03811115614fff57600080fd5b6020830191508360208260051b850101111561501a57600080fd5b9250929050565b60008060006040848603121561503657600080fd5b833561504181614fc1565b925060208401356001600160401b0381111561505c57600080fd5b61506886828701614fd6565b9497909650939450505050565b803563ffffffff8116811461508957600080fd5b919050565b600080604083850312156150a157600080fd5b82356150ac81614fc1565b91506150ba60208401615075565b90509250929050565b600080604083850312156150d657600080fd5b6150df83615075565b946020939093013593505050565b803560ff8116811461508957600080fd5b6001600160601b038116811461264157600080fd5b600080600080600080600080610100898b03121561513057600080fd5b61513989615075565b97506020890135965060408901359550606089013594506080890135935061516360a08a016150ed565b925060c0890135615173816150fe565b915060e0890135615183816150fe565b809150509295985092959890939650565b600061012082840312156151a757600080fd5b50919050565b6000806000606084860312156151c257600080fd5b83356151cd81614fc1565b925060208401356151dd81614fc1565b915060408401356001600160401b038111156151f857600080fd5b61520486828701615194565b9150509250925092565b60006020828403121561522057600080fd5b813561215b81614fc1565b6020808252825182820181905260009190848201906040850190845b818110156130fd5783516001600160601b031683529284019291840191600101615247565b6000806040838503121561527f57600080fd5b823561528a81614fc1565b9150602083013561529a81614fc1565b809150509250929050565b600080604083850312156152b857600080fd5b82356150df81614fc1565b6000602082840312156152d557600080fd5b61215b82615075565b600080604083850312156152f157600080fd5b61528a83615075565b6020808252825182820181905260009190848201906040850190845b818110156130fd5783516001600160a01b031683529284019291840191600101615316565b60008060006060848603121561535057600080fd5b833561535b81614fc1565b92506151dd60208501615075565b60008060006040848603121561537e57600080fd5b83356001600160401b0381111561539457600080fd5b6153a086828701614fd6565b90945092506153b3905060208501615075565b90509250925092565b6000806000606084860312156153d157600080fd5b83356153dc81614fc1565b95602085013595506040909401359392505050565b60208082528251828201819052600091906040908185019086840185805b8381101561544c57825185835b60028110156154395782518252918901919089019060010161541c565b505050938501939186019160010161540f565b509298975050505050505050565b60006020828403121561546c57600080fd5b81356001600160401b0381111561548257600080fd5b613a1384828501615194565b600080600080600080600060e0888a0312156154a957600080fd5b6154b288615075565b96506020880135955060408801359450606088013593506154d5608089016150ed565b925060a08801356154e5816150fe565b915060c08801356154f5816150fe565b8091505092959891949750929550565b6000806040838503121561551857600080fd5b823561552381614fc1565b915060208301356001600160401b0381111561553e57600080fd5b61554a85828601615194565b9150509250929050565b6020808252602d908201527f4f6e6c79204c616772616e676520736572766963652063616e2063616c6c207460408201526c3434b990333ab731ba34b7b71760991b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156155e1576155e16155b7565b5060010190565b600063ffffffff80831681811415615602576156026155b7565b6001019392505050565b634e487b7160e01b600052604160045260246000fd5b60208082526025908201527f5468652064656469636174656420636861696e206973206e6f742073756273636040820152641c9a58995960da1b606082015260800190565b6000821982111561567a5761567a6155b7565b500190565b600082821015615691576156916155b7565b500390565b60008160001904831182151516156156b0576156b06155b7565b500290565b6000808335601e198436030181126156cc57600080fd5b8301803591506001600160401b038211156156e657600080fd5b6020019150600681901b360382131561501a57600080fd5b60405160a081016001600160401b03811182821017156157205761572061560c565b60405290565b604080519081016001600160401b03811182821017156157205761572061560c565b604051601f8201601f191681016001600160401b03811182821017156157705761577061560c565b604052919050565b60006001600160401b038211156157915761579161560c565b5060051b60200190565b600082601f8301126157ac57600080fd5b6157b4615726565b8060408401858111156157c657600080fd5b845b818110156157e05780358452602093840193016157c8565b509095945050505050565b600082601f8301126157fc57600080fd5b615804615726565b80608084018581111561581657600080fd5b845b818110156157e05761582a878261579b565b8452602090930192604001615818565b6000610120823603121561584d57600080fd5b6158556156fe565b82356001600160401b0381111561586b57600080fd5b830136601f82011261587c57600080fd5b8035602061589161588c83615778565b615748565b82815260069290921b830181019181810190368411156158b057600080fd5b938201935b838510156158d9576158c7368661579b565b825282820191506040850194506158b5565b8552506158e8368783016157eb565b818501525050506158fc3660a0850161579b565b604082015260e083013560608201526101009092013560808301525090565b6020808252825182820181905260009190848201906040850190845b818110156130fd57835160ff1683529284019291840191600101615937565b6000602080838503121561596957600080fd5b82516001600160401b0381111561597f57600080fd5b8301601f8101851361599057600080fd5b805161599e61588c82615778565b81815260059190911b820183019083810190878311156159bd57600080fd5b928401925b828410156159e45783516159d581614fc1565b825292840192908401906159c2565b979650505050505050565b600060208284031215615a0157600080fd5b815161215b816150fe565b600060ff821680615a1f57615a1f6155b7565b6000190192915050565b600060ff821660ff841680821015615a4357615a436155b7565b90039392505050565b600060ff821660ff811415615a6357615a636155b7565b60010192915050565b60006001600160601b0380831681851681830481118215151615615a9257615a926155b7565b02949350505050565b634e487b7160e01b600052601260045260246000fd5b600082615ac057615ac0615a9b565b500490565b600081615ad457615ad46155b7565b506000190190565b634e487b7160e01b600052603160045260246000fd5b600082615b0157615b01615a9b565b50069056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47ded05fe36328e698032818f06b33ec59b066b9f59547700fa2bc365517f7f9a1424c534b6579436865636b65722e636865636b424c534b65795769746850726fa2646970667358221220c833c93e284de6dbca6bf208b651b7e267fea6fb52e11199bc7799286a3ee74164736f6c634300080c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f000000000000000000000000747dc3f9fe7df7a18dd79f6f40b3a1ed85aa75e8
-----Decoded View---------------
Arg [0] : _service (address): 0x34d8f7384Ddd4e8Ab447a150F9955f284882A43F
Arg [1] : _voteWeigher (address): 0x747dc3F9FE7df7A18DD79F6f40B3A1ed85aa75E8
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000034d8f7384ddd4e8ab447a150f9955f284882a43f
Arg [1] : 000000000000000000000000747dc3f9fe7df7a18dd79f6f40b3a1ed85aa75e8
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.