false
false
0

Contract Address Details

0xB5cC96c7831Db2b446eA5BD1b006020DD32B6d3a

Contract Name
CleanupBlockNumberManager
Creator
0x4598a6–d10d29 at 0xd58c1b–bdd2c0
Balance
0 FLR
Tokens
Fetching tokens...
Transactions
3 Transactions
Transfers
0 Transfers
Gas Used
185,637
Last Balance Update
23017006
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
CleanupBlockNumberManager




Optimization enabled
true
Compiler version
v0.7.6+commit.7338295f




Optimization runs
200
Verified at
2022-07-13T21:14:23.766638Z

Constructor Arguments

0000000000000000000000004598a6c05910ab914f0cbaaca1911cd337d10d29000000000000000000000000baf89d873d198ff78e72d2745b01cba3c6e5be6b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000b4674736f4d616e61676572000000000000000000000000000000000000000000

Arg [0] (address) : 0x4598a6c05910ab914f0cbaaca1911cd337d10d29
Arg [1] (address) : 0xbaf89d873d198ff78e72d2745b01cba3c6e5be6b
Arg [2] (string) : FtsoManager

              

./contracts/token/implementation/CleanupBlockNumberManager.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;

import "../../governance/implementation/Governed.sol";
import "../../addressUpdater/implementation/AddressUpdatable.sol";
import "../../token/interface/IICleanable.sol";


/**
 * @title Token history cleanup manager
 * @notice Maintains the list of cleanable tokens for which history cleanup can be collectively cleaned u 
 */
contract CleanupBlockNumberManager is Governed, AddressUpdatable {

    string internal constant ERR_CONTRACT_NOT_FOUND = "contract not found";
    string internal constant ERR_TRIGGER_CONTRACT_ONLY = "trigger contract only";

    IICleanable[] public registeredTokens;
    address public triggerContract;
    string public triggerContractName; // needed for updating trigger contract through AddressUpdater call

    event RegistrationUpdated (IICleanable theContract, bool add);
    event CleanupBlockNumberSet (IICleanable theContract, uint256 blockNumber, bool success);
        
    modifier onlyTrigger {
        require(msg.sender == triggerContract, ERR_TRIGGER_CONTRACT_ONLY);
        _;
    }

    constructor(
        address _governance,
        address _addressUpdater,
        string memory _triggerContractName
    )
        Governed(_governance) AddressUpdatable(_addressUpdater)
    {
        triggerContractName = _triggerContractName;
    }

    /**
     * @notice Register a contract of which history cleanup index is to be managed
     * @param _cleanableToken     The address of the contract to be managed.
     * @dev when using this function take care that call of setCleanupBlockNumber
     * is permitted by this object
     */
    function registerToken(IICleanable _cleanableToken) external onlyGovernance {
        uint256 len = registeredTokens.length;

        for (uint256 i = 0; i < len; i++) {
            if (_cleanableToken == registeredTokens[i]) {
                return; // already registered
            }
        }

        registeredTokens.push(_cleanableToken);
        emit RegistrationUpdated (_cleanableToken, true);
    }

    /**
     * @notice Unregiseter a contract from history cleanup index management
     * @param _cleanableToken     The address of the contract to unregister.
     */
    function unregisterToken(IICleanable _cleanableToken) external onlyGovernance {        
        uint256 len = registeredTokens.length;

        for (uint256 i = 0; i < len; i++) {
            if (_cleanableToken == registeredTokens[i]) {
                registeredTokens[i] = registeredTokens[len -1];
                registeredTokens.pop();
                emit RegistrationUpdated (_cleanableToken, false);
                return;
            }
        }

        revert(ERR_CONTRACT_NOT_FOUND);
    }

    /**
     * @notice Sets clean up block number on managed cleanable tokens
     * @param _blockNumber cleanup block number
     */
    function setCleanUpBlockNumber(uint256 _blockNumber) external onlyTrigger {
        uint256 len = registeredTokens.length;
        for (uint256 i = 0; i < len; i++) {
            try registeredTokens[i].setCleanupBlockNumber(_blockNumber) {
                emit CleanupBlockNumberSet(registeredTokens[i], _blockNumber, true);
            } catch {
                emit CleanupBlockNumberSet(registeredTokens[i], _blockNumber, false);
            }
        }
    }

    /**
     * @notice Implementation of the AddressUpdatable abstract method.
     */
    function _updateContractAddresses(
        bytes32[] memory _contractNameHashes,
        address[] memory _contractAddresses
    )
        internal override
    {
        triggerContract = _getContractAddress(_contractNameHashes, _contractAddresses, triggerContractName);
    }
}
        

./contracts/addressUpdater/implementation/AddressUpdatable.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;

import "../interface/IIAddressUpdatable.sol";


abstract contract AddressUpdatable is IIAddressUpdatable {

    // https://docs.soliditylang.org/en/v0.8.7/contracts.html#constant-and-immutable-state-variables
    // No storage slot is allocated
    bytes32 internal constant ADDRESS_STORAGE_POSITION = 
        keccak256("flare.diamond.AddressUpdatable.ADDRESS_STORAGE_POSITION");

    modifier onlyAddressUpdater() {
        require (msg.sender == getAddressUpdater(), "only address updater");
        _;
    }

    constructor(address _addressUpdater) {
        setAddressUpdaterValue(_addressUpdater);
    }

    function getAddressUpdater() public view returns (address _addressUpdater) {
        // Only direct constants are allowed in inline assembly, so we assign it here
        bytes32 position = ADDRESS_STORAGE_POSITION;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            _addressUpdater := sload(position)
        }
    }

    /**
     * @notice external method called from AddressUpdater only
     */
    function updateContractAddresses(
        bytes32[] memory _contractNameHashes,
        address[] memory _contractAddresses
    )
        external override
        onlyAddressUpdater
    {
        // update addressUpdater address
        setAddressUpdaterValue(_getContractAddress(_contractNameHashes, _contractAddresses, "AddressUpdater"));
        // update all other addresses
        _updateContractAddresses(_contractNameHashes, _contractAddresses);
    }

    /**
     * @notice virtual method that a contract extending AddressUpdatable must implement
     */
    function _updateContractAddresses(
        bytes32[] memory _contractNameHashes,
        address[] memory _contractAddresses
    ) internal virtual;

    /**
     * @notice helper method to get contract address
     * @dev it reverts if contract name does not exist
     */
    function _getContractAddress(
        bytes32[] memory _nameHashes,
        address[] memory _addresses,
        string memory _nameToFind
    )
        internal pure
        returns(address)
    {
        bytes32 nameHash = keccak256(abi.encode(_nameToFind));
        address a = address(0);
        for (uint256 i = 0; i < _nameHashes.length; i++) {
            if (nameHash == _nameHashes[i]) {
                a = _addresses[i];
                break;
            }
        }
        require(a != address(0), "address zero");
        return a;
    }

    function setAddressUpdaterValue(address _addressUpdater) internal {
        // Only direct constants are allowed in inline assembly, so we assign it here
        bytes32 position = ADDRESS_STORAGE_POSITION;
        // solhint-disable-next-line no-inline-assembly  
        assembly {
            sstore(position, _addressUpdater)
        }
    }
}
          

./contracts/addressUpdater/interface/IIAddressUpdatable.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.6 <0.9;


interface IIAddressUpdatable {
    /**
     * @notice Updates contract addresses - should be called only from AddressUpdater contract
     * @param _contractNameHashes       list of keccak256(abi.encode(...)) contract names
     * @param _contractAddresses        list of contract addresses corresponding to the contract names
     */
    function updateContractAddresses(
        bytes32[] memory _contractNameHashes,
        address[] memory _contractAddresses
        ) external;
}
          

./contracts/governance/implementation/Governed.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;

import { GovernedBase } from "./GovernedBase.sol";


/**
 * @title Governed
 * @dev For deployed, governed contracts, enforce a non-zero address at create time.
 **/
contract Governed is GovernedBase {
    constructor(address _governance) GovernedBase(_governance) {
        require(_governance != address(0), "_governance zero");
    }
}
          

./contracts/governance/implementation/GovernedBase.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;

import "../../userInterfaces/IGovernanceSettings.sol";


/**
 * @title Governed Base
 * @notice This abstract base class defines behaviors for a governed contract.
 * @dev This class is abstract so that specific behaviors can be defined for the constructor.
 *   Contracts should not be left ungoverned, but not all contract will have a constructor
 *   (for example those pre-defined in genesis).
 **/
abstract contract GovernedBase {
    struct TimelockedCall {
        uint256 allowedAfterTimestamp;
        bytes encodedCall;
    }
    
    // solhint-disable-next-line const-name-snakecase
    IGovernanceSettings public constant governanceSettings = 
        IGovernanceSettings(0x1000000000000000000000000000000000000007);

    address private initialGovernance;

    bool private initialised;
    
    bool public productionMode;
    
    bool private executing;
    
    mapping(bytes4 => TimelockedCall) public timelockedCalls;
    
    event GovernanceCallTimelocked(bytes4 selector, uint256 allowedAfterTimestamp, bytes encodedCall);
    event TimelockedGovernanceCallExecuted(bytes4 selector, uint256 timestamp);
    event TimelockedGovernanceCallCanceled(bytes4 selector, uint256 timestamp);
    
    event GovernanceInitialised(address initialGovernance);
    event GovernedProductionModeEntered(address governanceSettings);
    
    modifier onlyGovernance {
        if (executing || !productionMode) {
            _beforeExecute();
            _;
        } else {
            _recordTimelockedCall(msg.data);
        }
    }
    
    modifier onlyImmediateGovernance () {
        _checkOnlyGovernance();
        _;
    }

    constructor(address _initialGovernance) {
        if (_initialGovernance != address(0)) {
            initialise(_initialGovernance);
        }
    }

    /**
     * @notice Execute the timelocked governance calls once the timelock period expires.
     * @dev Only executor can call this method.
     * @param _selector The method selector (only one timelocked call per method is stored).
     */
    function executeGovernanceCall(bytes4 _selector) external {
        require(governanceSettings.isExecutor(msg.sender), "only executor");
        TimelockedCall storage call = timelockedCalls[_selector];
        require(call.allowedAfterTimestamp != 0, "timelock: invalid selector");
        require(block.timestamp >= call.allowedAfterTimestamp, "timelock: not allowed yet");
        bytes memory encodedCall = call.encodedCall;
        delete timelockedCalls[_selector];
        executing = true;
        //solhint-disable-next-line avoid-low-level-calls
        (bool success,) = address(this).call(encodedCall);
        executing = false;
        emit TimelockedGovernanceCallExecuted(_selector, block.timestamp);
        _passReturnOrRevert(success);
    }
    
    /**
     * Cancel a timelocked governance call before it has been executed.
     * @dev Only governance can call this method.
     * @param _selector The method selector.
     */
    function cancelGovernanceCall(bytes4 _selector) external onlyImmediateGovernance {
        require(timelockedCalls[_selector].allowedAfterTimestamp != 0, "timelock: invalid selector");
        emit TimelockedGovernanceCallCanceled(_selector, block.timestamp);
        delete timelockedCalls[_selector];
    }
    
    /**
     * Enter the production mode after all the initial governance settings have been set.
     * This enables timelocks and the governance is afterwards obtained by calling 
     * governanceSettings.getGovernanceAddress(). 
     */
    function switchToProductionMode() external {
        _checkOnlyGovernance();
        require(!productionMode, "already in production mode");
        initialGovernance = address(0);
        productionMode = true;
        emit GovernedProductionModeEntered(address(governanceSettings));
    }

    /**
     * @notice Initialize the governance address if not first initialized.
     */
    function initialise(address _initialGovernance) public virtual {
        require(initialised == false, "initialised != false");
        initialised = true;
        initialGovernance = _initialGovernance;
        emit GovernanceInitialised(_initialGovernance);
    }
    
    /**
     * Returns the current effective governance address.
     */
    function governance() public view returns (address) {
        return productionMode ? governanceSettings.getGovernanceAddress() : initialGovernance;
    }

    function _beforeExecute() private {
        if (executing) {
            // can only be run from executeGovernanceCall(), where we check that only executor can call
            // make sure nothing else gets executed, even in case of reentrancy
            assert(msg.sender == address(this));
            executing = false;
        } else {
            // must be called with: productionMode=false
            // must check governance in this case
            _checkOnlyGovernance();
        }
    }

    function _recordTimelockedCall(bytes calldata _data) private {
        _checkOnlyGovernance();
        bytes4 selector;
        //solhint-disable-next-line no-inline-assembly
        assembly {
            selector := calldataload(_data.offset)
        }
        uint256 timelock = governanceSettings.getTimelock();
        uint256 allowedAt = block.timestamp + timelock;
        timelockedCalls[selector] = TimelockedCall({
            allowedAfterTimestamp: allowedAt,
            encodedCall: _data
        });
        emit GovernanceCallTimelocked(selector, allowedAt, _data);
    }
    
    function _checkOnlyGovernance() private view {
        require(msg.sender == governance(), "only governance");
    }
    
    function _passReturnOrRevert(bool _success) private pure {
        // pass exact return or revert data - needs to be done in assembly
        //solhint-disable-next-line no-inline-assembly
        assembly {
            let size := returndatasize()
            let ptr := mload(0x40)
            mstore(0x40, add(ptr, size))
            returndatacopy(ptr, 0, size)
            if _success {
                return(ptr, size)
            }
            revert(ptr, size)
        }
    }
}
          

./contracts/token/interface/IICleanable.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.6 <0.9;

interface IICleanable {
    /**
     * Set the contract that is allowed to call history cleaning methods.
     */
    function setCleanerContract(address _cleanerContract) external;
    
    /**
     * Set the cleanup block number.
     * Historic data for the blocks before `cleanupBlockNumber` can be erased,
     * history before that block should never be used since it can be inconsistent.
     * In particular, cleanup block number must be before current vote power block.
     * @param _blockNumber The new cleanup block number.
     */
    function setCleanupBlockNumber(uint256 _blockNumber) external;
    
    /**
     * Get the current cleanup block number.
     */
    function cleanupBlockNumber() external view returns (uint256);
}
          

./contracts/userInterfaces/IGovernanceSettings.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;


/**
 * A special contract that holds Flare governance address.
 * This contract enables updating governance address and timelock only by hard forking the network,
 * meaning only by updating validator code.
 */
interface IGovernanceSettings {
    /**
     * Get the governance account address.
     * The governance address can only be changed by a hardfork.
     */
    function getGovernanceAddress() external view returns (address);
    
    /**
     * Get the time in seconds that must pass between a governance call and execution.
     * The timelock value can only be changed by a hardfork.
     */
    function getTimelock() external view returns (uint256);
    
    /**
     * Get the addresses of the accounts that are allowed to execute the timelocked governance calls
     * once the timelock period expires.
     * Executors can be changed without a hardfork, via a normal governance call.
     */
    function getExecutors() external view returns (address[] memory);
    
    /**
     * Check whether an address is one of the executors.
     */
    function isExecutor(address _address) external view returns (bool);
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_governance","internalType":"address"},{"type":"address","name":"_addressUpdater","internalType":"address"},{"type":"string","name":"_triggerContractName","internalType":"string"}]},{"type":"event","name":"CleanupBlockNumberSet","inputs":[{"type":"address","name":"theContract","internalType":"contract IICleanable","indexed":false},{"type":"uint256","name":"blockNumber","internalType":"uint256","indexed":false},{"type":"bool","name":"success","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceCallTimelocked","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256","indexed":false},{"type":"bytes","name":"encodedCall","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceInitialised","inputs":[{"type":"address","name":"initialGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernedProductionModeEntered","inputs":[{"type":"address","name":"governanceSettings","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"RegistrationUpdated","inputs":[{"type":"address","name":"theContract","internalType":"contract IICleanable","indexed":false},{"type":"bool","name":"add","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallCanceled","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallExecuted","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"_addressUpdater","internalType":"address"}],"name":"getAddressUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IGovernanceSettings"}],"name":"governanceSettings","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_initialGovernance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"productionMode","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"registerToken","inputs":[{"type":"address","name":"_cleanableToken","internalType":"contract IICleanable"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IICleanable"}],"name":"registeredTokens","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setCleanUpBlockNumber","inputs":[{"type":"uint256","name":"_blockNumber","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"switchToProductionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256"},{"type":"bytes","name":"encodedCall","internalType":"bytes"}],"name":"timelockedCalls","inputs":[{"type":"bytes4","name":"","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"triggerContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"triggerContractName","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unregisterToken","inputs":[{"type":"address","name":"_cleanableToken","internalType":"contract IICleanable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateContractAddresses","inputs":[{"type":"bytes32[]","name":"_contractNameHashes","internalType":"bytes32[]"},{"type":"address[]","name":"_contractAddresses","internalType":"address[]"}]}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b5060405162001ad138038062001ad1833981810160405260608110156200003757600080fd5b815160208301516040808501805191519395929483019291846401000000008211156200006357600080fd5b9083019060208201858111156200007957600080fd5b82516401000000008111828201881017156200009457600080fd5b82525081516020918201929091019080838360005b83811015620000c3578181015183820152602001620000a9565b50505050905090810190601f168015620000f15780820380516001836020036101000a031916815260200191505b5060405250839150849050806001600160a01b038116156200011857620001188162000194565b506001600160a01b03811662000168576040805162461bcd60e51b815260206004820152601060248201526f5f676f7665726e616e6365207a65726f60801b604482015290519081900360640190fd5b50620001748162000257565b5080516200018a9060049060208401906200027b565b5050505062000327565b600054600160a01b900460ff1615620001f4576040805162461bcd60e51b815260206004820152601460248201527f696e697469616c6973656420213d2066616c7365000000000000000000000000604482015290519081900360640190fd5b60008054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b03831690811790915560408051918252517f9789733827840833afc031fb2ef9ab6894271f77bad2085687cf4ae5c7bee4db916020908290030190a150565b7f714f205b2abd25bef1d06a1af944e38c113fe6160375c4e1d6d5cf28848e771955565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620002b35760008555620002fe565b82601f10620002ce57805160ff1916838001178555620002fe565b82800160010185558215620002fe579182015b82811115620002fe578251825591602001919060010190620002e1565b506200030c92915062000310565b5090565b5b808211156200030c576000815560010162000311565b61179a80620003376000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80639a0ba2ea11610097578063cbc31cf711610066578063cbc31cf714610462578063d2b799ad1461047f578063e17f212e14610487578063f5a98383146104a357610100565b80639a0ba2ea1461027b5780639d6a890f14610298578063b00c0b76146102be578063c1ce5578146103e557610100565b806362354e03116100d357806362354e031461018057806367fc40291461018857806374e6310e146101af57806377860cdd1461025557610100565b806309824a80146101055780635267a15d1461012d5780635aa6e675146101515780635ff2707914610159575b600080fd5b61012b6004803603602081101561011b57600080fd5b50356001600160a01b03166104ab565b005b6101356105c4565b604080516001600160a01b039092168252519081900360200190f35b6101356105e9565b61012b6004803603602081101561016f57600080fd5b50356001600160e01b03191661067e565b6101356109d3565b61012b6004803603602081101561019e57600080fd5b50356001600160e01b0319166109de565b6101d6600480360360208110156101c557600080fd5b50356001600160e01b031916610ac6565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610219578181015183820152602001610201565b50505050905090810190601f1680156102465780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b61012b6004803603602081101561026b57600080fd5b50356001600160a01b0316610b6c565b6101356004803603602081101561029157600080fd5b5035610d6d565b61012b600480360360208110156102ae57600080fd5b50356001600160a01b0316610d97565b61012b600480360360408110156102d457600080fd5b8101906020810181356401000000008111156102ef57600080fd5b82018360208201111561030157600080fd5b8035906020019184602083028401116401000000008311171561032357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929594936020810193503591505064010000000081111561037357600080fd5b82018360208201111561038557600080fd5b803590602001918460208302840111640100000000831117156103a757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610e50945050505050565b6103ed610efb565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561042757818101518382015260200161040f565b50505050905090810190601f1680156104545780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61012b6004803603602081101561047857600080fd5b5035610f89565b610135611164565b61048f611173565b604080519115158252519081900360200190f35b61012b611183565b600054600160b01b900460ff16806104cd5750600054600160a81b900460ff16155b156105b6576104da61123d565b60025460005b8181101561052357600281815481106104f557fe5b6000918252602090912001546001600160a01b038481169116141561051b5750506105b1565b6001016104e0565b5060028054600180820183556000929092527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b03851690811790915560408051918252602082019290925281517f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb59929181900390910190a1505b6105c1565b6105c1600036611274565b50565b7f714f205b2abd25bef1d06a1af944e38c113fe6160375c4e1d6d5cf28848e77195490565b60008054600160a81b900460ff1661060c576000546001600160a01b0316610679565b60076001609c1b016001600160a01b031663732524946040518163ffffffff1660e01b815260040160206040518083038186803b15801561064c57600080fd5b505afa158015610660573d6000803e3d6000fd5b505050506040513d602081101561067657600080fd5b50515b905090565b60408051630debfda360e41b8152336004820152905160076001609c1b019163debfda30916024808301926020929190829003018186803b1580156106c257600080fd5b505afa1580156106d6573d6000803e3d6000fd5b505050506040513d60208110156106ec57600080fd5b505161072f576040805162461bcd60e51b815260206004820152600d60248201526c37b7363c9032bc32b1baba37b960991b604482015290519081900360640190fd5b6001600160e01b031981166000908152600160205260409020805461079b576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b80544210156107f1576040805162461bcd60e51b815260206004820152601960248201527f74696d656c6f636b3a206e6f7420616c6c6f7765642079657400000000000000604482015290519081900360640190fd5b6000816001018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561088b5780601f106108605761010080835404028352916020019161088b565b820191906000526020600020905b81548152906001019060200180831161086e57829003601f168201915b5050506001600160e01b03198616600090815260016020819052604082208281559495509092506108bf915083018261167f565b50506000805460ff60b01b1916600160b01b178155604051825130918491819060208401908083835b602083106109075780518252601f1990920191602091820191016108e8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610969576040519150601f19603f3d011682016040523d82523d6000602084013e61096e565b606091505b50506000805460ff60b01b19169055604080516001600160e01b03198716815242602082015281519293507fa7326b57fc9cfe267aaea5e7f0b01757154d265620a0585819416ee9ddd2c438929081900390910190a16109cd816113f7565b50505050565b60076001609c1b0181565b6109e6611414565b6001600160e01b03198116600090815260016020526040902054610a51576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b604080516001600160e01b03198316815242602082015281517f7735b2391c38a81419c513e30ca578db7158eadd7101511b23e221c654d19cf8929181900390910190a16001600160e01b03198116600090815260016020819052604082208281559190610ac19083018261167f565b505050565b600160208181526000928352604092839020805481840180548651600296821615610100026000190190911695909504601f81018590048502860185019096528585529094919392909190830182828015610b625780601f10610b3757610100808354040283529160200191610b62565b820191906000526020600020905b815481529060010190602001808311610b4557829003601f168201915b5050505050905082565b600054600160b01b900460ff1680610b8e5750600054600160a81b900460ff16155b156105b657610b9b61123d565b60025460005b81811015610cbd5760028181548110610bb657fe5b6000918252602090912001546001600160a01b0384811691161415610cb55760026001830381548110610be557fe5b600091825260209091200154600280546001600160a01b039092169183908110610c0b57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506002805480610c4457fe5b60008281526020808220830160001990810180546001600160a01b0319169055909201909255604080516001600160a01b03871681529182019290925281517f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb59929181900390910190a150506105b1565b600101610ba1565b506040518060400160405280601281526020017118dbdb9d1c9858dd081b9bdd08199bdd5b9960721b81525060405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d32578181015183820152602001610d1a565b50505050905090810190601f168015610d5f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60028181548110610d7d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600054600160a01b900460ff1615610ded576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b60008054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b03831690811790915560408051918252517f9789733827840833afc031fb2ef9ab6894271f77bad2085687cf4ae5c7bee4db916020908290030190a150565b610e586105c4565b6001600160a01b0316336001600160a01b031614610eb4576040805162461bcd60e51b815260206004820152601460248201527337b7363c9030b2323932b9b9903ab83230ba32b960611b604482015290519081900360640190fd5b610eed610ee883836040518060400160405280600e81526020016d20b2323932b9b9aab83230ba32b960911b815250611473565b6115a0565b610ef782826115c4565b5050565b6004805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610f815780601f10610f5657610100808354040283529160200191610f81565b820191906000526020600020905b815481529060010190602001808311610f6457829003601f168201915b505050505081565b6003546040805180820190915260158152747472696767657220636f6e7472616374206f6e6c7960581b6020820152906001600160a01b0316331461100f5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d32578181015183820152602001610d1a565b5060025460005b81811015610ac1576002818154811061102b57fe5b6000918252602082200154604080516313de97f560e01b81526004810187905290516001600160a01b03909216926313de97f59260248084019382900301818387803b15801561107a57600080fd5b505af192505050801561108b575060015b6110f8577f6e31dc4aae4e8c2369947a8179952c1929b7af7bc75f57e71ebce5d37e62eae7600282815481106110bd57fe5b6000918252602080832090910154604080516001600160a01b03909216825291810187905280820192909252519081900360600190a161115c565b7f6e31dc4aae4e8c2369947a8179952c1929b7af7bc75f57e71ebce5d37e62eae76002828154811061112657fe5b60009182526020918290200154604080516001600160a01b03909216825291810186905260018183015290519081900360600190a15b600101611016565b6003546001600160a01b031681565b600054600160a81b900460ff1681565b61118b611414565b600054600160a81b900460ff16156111ea576040805162461bcd60e51b815260206004820152601a60248201527f616c726561647920696e2070726f64756374696f6e206d6f6465000000000000604482015290519081900360640190fd5b60008054600161ff0160a01b031916600160a81b1790556040805160076001609c1b01815290517f83af113638b5422f9e977cebc0aaf0eaf2188eb9a8baae7f9d46c42b33a1560c9181900360200190a1565b600054600160b01b900460ff161561126a5733301461125857fe5b6000805460ff60b01b19169055611272565b611272611414565b565b61127c611414565b600082359050600060076001609c1b016001600160a01b0316636221a54b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112c457600080fd5b505afa1580156112d8573d6000803e3d6000fd5b505050506040513d60208110156112ee57600080fd5b505160408051808201825242830180825282516020601f89018190048102820181019094528781529394509290918281019190889088908190840183828082843760009201829052509390945250506001600160e01b03198616815260016020818152604090922084518155848301518051919450611372939285019201906116c3565b509050507fed948300a3694aa01d4a6b258bfd664350193d770c0b51f8387277f6d83ea3b68382878760405180856001600160e01b0319168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a15050505050565b3d604051818101604052816000823e8215611410578181f35b8181fd5b61141c6105e9565b6001600160a01b0316336001600160a01b031614611272576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600080826040516020018080602001828103825283818151815260200191508051906020019080838360005b838110156114b757818101518382015260200161149f565b50505050905090810190601f1680156114e45780820380516001836020036101000a031916815260200191505b50925050506040516020818303038152906040528051906020012090506000805b865181101561154c5786818151811061151a57fe5b60200260200101518314156115445785818151811061153557fe5b6020026020010151915061154c565b600101611505565b506001600160a01b038116611597576040805162461bcd60e51b815260206004820152600c60248201526b61646472657373207a65726f60a01b604482015290519081900360640190fd5b95945050505050565b7f714f205b2abd25bef1d06a1af944e38c113fe6160375c4e1d6d5cf28848e771955565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815261165b93869386938301828280156116515780601f1061162657610100808354040283529160200191611651565b820191906000526020600020905b81548152906001019060200180831161163457829003601f168201915b5050505050611473565b600380546001600160a01b0319166001600160a01b03929092169190911790555050565b50805460018160011615610100020316600290046000825580601f106116a557506105c1565b601f0160209004906000526020600020908101906105c1919061174f565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826116f9576000855561173f565b82601f1061171257805160ff191683800117855561173f565b8280016001018555821561173f579182015b8281111561173f578251825591602001919060010190611724565b5061174b92915061174f565b5090565b5b8082111561174b576000815560010161175056fea2646970667358221220736a2399bdf76a19b64e33a6c08f0b184644654aeb8ec3c3bc6a60fb7f1b4d8064736f6c634300070600330000000000000000000000004598a6c05910ab914f0cbaaca1911cd337d10d29000000000000000000000000baf89d873d198ff78e72d2745b01cba3c6e5be6b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000b4674736f4d616e61676572000000000000000000000000000000000000000000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101005760003560e01c80639a0ba2ea11610097578063cbc31cf711610066578063cbc31cf714610462578063d2b799ad1461047f578063e17f212e14610487578063f5a98383146104a357610100565b80639a0ba2ea1461027b5780639d6a890f14610298578063b00c0b76146102be578063c1ce5578146103e557610100565b806362354e03116100d357806362354e031461018057806367fc40291461018857806374e6310e146101af57806377860cdd1461025557610100565b806309824a80146101055780635267a15d1461012d5780635aa6e675146101515780635ff2707914610159575b600080fd5b61012b6004803603602081101561011b57600080fd5b50356001600160a01b03166104ab565b005b6101356105c4565b604080516001600160a01b039092168252519081900360200190f35b6101356105e9565b61012b6004803603602081101561016f57600080fd5b50356001600160e01b03191661067e565b6101356109d3565b61012b6004803603602081101561019e57600080fd5b50356001600160e01b0319166109de565b6101d6600480360360208110156101c557600080fd5b50356001600160e01b031916610ac6565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610219578181015183820152602001610201565b50505050905090810190601f1680156102465780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b61012b6004803603602081101561026b57600080fd5b50356001600160a01b0316610b6c565b6101356004803603602081101561029157600080fd5b5035610d6d565b61012b600480360360208110156102ae57600080fd5b50356001600160a01b0316610d97565b61012b600480360360408110156102d457600080fd5b8101906020810181356401000000008111156102ef57600080fd5b82018360208201111561030157600080fd5b8035906020019184602083028401116401000000008311171561032357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929594936020810193503591505064010000000081111561037357600080fd5b82018360208201111561038557600080fd5b803590602001918460208302840111640100000000831117156103a757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610e50945050505050565b6103ed610efb565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561042757818101518382015260200161040f565b50505050905090810190601f1680156104545780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61012b6004803603602081101561047857600080fd5b5035610f89565b610135611164565b61048f611173565b604080519115158252519081900360200190f35b61012b611183565b600054600160b01b900460ff16806104cd5750600054600160a81b900460ff16155b156105b6576104da61123d565b60025460005b8181101561052357600281815481106104f557fe5b6000918252602090912001546001600160a01b038481169116141561051b5750506105b1565b6001016104e0565b5060028054600180820183556000929092527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b03851690811790915560408051918252602082019290925281517f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb59929181900390910190a1505b6105c1565b6105c1600036611274565b50565b7f714f205b2abd25bef1d06a1af944e38c113fe6160375c4e1d6d5cf28848e77195490565b60008054600160a81b900460ff1661060c576000546001600160a01b0316610679565b60076001609c1b016001600160a01b031663732524946040518163ffffffff1660e01b815260040160206040518083038186803b15801561064c57600080fd5b505afa158015610660573d6000803e3d6000fd5b505050506040513d602081101561067657600080fd5b50515b905090565b60408051630debfda360e41b8152336004820152905160076001609c1b019163debfda30916024808301926020929190829003018186803b1580156106c257600080fd5b505afa1580156106d6573d6000803e3d6000fd5b505050506040513d60208110156106ec57600080fd5b505161072f576040805162461bcd60e51b815260206004820152600d60248201526c37b7363c9032bc32b1baba37b960991b604482015290519081900360640190fd5b6001600160e01b031981166000908152600160205260409020805461079b576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b80544210156107f1576040805162461bcd60e51b815260206004820152601960248201527f74696d656c6f636b3a206e6f7420616c6c6f7765642079657400000000000000604482015290519081900360640190fd5b6000816001018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561088b5780601f106108605761010080835404028352916020019161088b565b820191906000526020600020905b81548152906001019060200180831161086e57829003601f168201915b5050506001600160e01b03198616600090815260016020819052604082208281559495509092506108bf915083018261167f565b50506000805460ff60b01b1916600160b01b178155604051825130918491819060208401908083835b602083106109075780518252601f1990920191602091820191016108e8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610969576040519150601f19603f3d011682016040523d82523d6000602084013e61096e565b606091505b50506000805460ff60b01b19169055604080516001600160e01b03198716815242602082015281519293507fa7326b57fc9cfe267aaea5e7f0b01757154d265620a0585819416ee9ddd2c438929081900390910190a16109cd816113f7565b50505050565b60076001609c1b0181565b6109e6611414565b6001600160e01b03198116600090815260016020526040902054610a51576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b604080516001600160e01b03198316815242602082015281517f7735b2391c38a81419c513e30ca578db7158eadd7101511b23e221c654d19cf8929181900390910190a16001600160e01b03198116600090815260016020819052604082208281559190610ac19083018261167f565b505050565b600160208181526000928352604092839020805481840180548651600296821615610100026000190190911695909504601f81018590048502860185019096528585529094919392909190830182828015610b625780601f10610b3757610100808354040283529160200191610b62565b820191906000526020600020905b815481529060010190602001808311610b4557829003601f168201915b5050505050905082565b600054600160b01b900460ff1680610b8e5750600054600160a81b900460ff16155b156105b657610b9b61123d565b60025460005b81811015610cbd5760028181548110610bb657fe5b6000918252602090912001546001600160a01b0384811691161415610cb55760026001830381548110610be557fe5b600091825260209091200154600280546001600160a01b039092169183908110610c0b57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506002805480610c4457fe5b60008281526020808220830160001990810180546001600160a01b0319169055909201909255604080516001600160a01b03871681529182019290925281517f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb59929181900390910190a150506105b1565b600101610ba1565b506040518060400160405280601281526020017118dbdb9d1c9858dd081b9bdd08199bdd5b9960721b81525060405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d32578181015183820152602001610d1a565b50505050905090810190601f168015610d5f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60028181548110610d7d57600080fd5b6000918252602090912001546001600160a01b0316905081565b600054600160a01b900460ff1615610ded576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b60008054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b03831690811790915560408051918252517f9789733827840833afc031fb2ef9ab6894271f77bad2085687cf4ae5c7bee4db916020908290030190a150565b610e586105c4565b6001600160a01b0316336001600160a01b031614610eb4576040805162461bcd60e51b815260206004820152601460248201527337b7363c9030b2323932b9b9903ab83230ba32b960611b604482015290519081900360640190fd5b610eed610ee883836040518060400160405280600e81526020016d20b2323932b9b9aab83230ba32b960911b815250611473565b6115a0565b610ef782826115c4565b5050565b6004805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610f815780601f10610f5657610100808354040283529160200191610f81565b820191906000526020600020905b815481529060010190602001808311610f6457829003601f168201915b505050505081565b6003546040805180820190915260158152747472696767657220636f6e7472616374206f6e6c7960581b6020820152906001600160a01b0316331461100f5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d32578181015183820152602001610d1a565b5060025460005b81811015610ac1576002818154811061102b57fe5b6000918252602082200154604080516313de97f560e01b81526004810187905290516001600160a01b03909216926313de97f59260248084019382900301818387803b15801561107a57600080fd5b505af192505050801561108b575060015b6110f8577f6e31dc4aae4e8c2369947a8179952c1929b7af7bc75f57e71ebce5d37e62eae7600282815481106110bd57fe5b6000918252602080832090910154604080516001600160a01b03909216825291810187905280820192909252519081900360600190a161115c565b7f6e31dc4aae4e8c2369947a8179952c1929b7af7bc75f57e71ebce5d37e62eae76002828154811061112657fe5b60009182526020918290200154604080516001600160a01b03909216825291810186905260018183015290519081900360600190a15b600101611016565b6003546001600160a01b031681565b600054600160a81b900460ff1681565b61118b611414565b600054600160a81b900460ff16156111ea576040805162461bcd60e51b815260206004820152601a60248201527f616c726561647920696e2070726f64756374696f6e206d6f6465000000000000604482015290519081900360640190fd5b60008054600161ff0160a01b031916600160a81b1790556040805160076001609c1b01815290517f83af113638b5422f9e977cebc0aaf0eaf2188eb9a8baae7f9d46c42b33a1560c9181900360200190a1565b600054600160b01b900460ff161561126a5733301461125857fe5b6000805460ff60b01b19169055611272565b611272611414565b565b61127c611414565b600082359050600060076001609c1b016001600160a01b0316636221a54b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112c457600080fd5b505afa1580156112d8573d6000803e3d6000fd5b505050506040513d60208110156112ee57600080fd5b505160408051808201825242830180825282516020601f89018190048102820181019094528781529394509290918281019190889088908190840183828082843760009201829052509390945250506001600160e01b03198616815260016020818152604090922084518155848301518051919450611372939285019201906116c3565b509050507fed948300a3694aa01d4a6b258bfd664350193d770c0b51f8387277f6d83ea3b68382878760405180856001600160e01b0319168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a15050505050565b3d604051818101604052816000823e8215611410578181f35b8181fd5b61141c6105e9565b6001600160a01b0316336001600160a01b031614611272576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b600080826040516020018080602001828103825283818151815260200191508051906020019080838360005b838110156114b757818101518382015260200161149f565b50505050905090810190601f1680156114e45780820380516001836020036101000a031916815260200191505b50925050506040516020818303038152906040528051906020012090506000805b865181101561154c5786818151811061151a57fe5b60200260200101518314156115445785818151811061153557fe5b6020026020010151915061154c565b600101611505565b506001600160a01b038116611597576040805162461bcd60e51b815260206004820152600c60248201526b61646472657373207a65726f60a01b604482015290519081900360640190fd5b95945050505050565b7f714f205b2abd25bef1d06a1af944e38c113fe6160375c4e1d6d5cf28848e771955565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815261165b93869386938301828280156116515780601f1061162657610100808354040283529160200191611651565b820191906000526020600020905b81548152906001019060200180831161163457829003601f168201915b5050505050611473565b600380546001600160a01b0319166001600160a01b03929092169190911790555050565b50805460018160011615610100020316600290046000825580601f106116a557506105c1565b601f0160209004906000526020600020908101906105c1919061174f565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826116f9576000855561173f565b82601f1061171257805160ff191683800117855561173f565b8280016001018555821561173f579182015b8281111561173f578251825591602001919060010190611724565b5061174b92915061174f565b5090565b5b8082111561174b576000815560010161175056fea2646970667358221220736a2399bdf76a19b64e33a6c08f0b184644654aeb8ec3c3bc6a60fb7f1b4d8064736f6c63430007060033