Contract 0x5769d84dd62a6fd969856c75c7d321b84d455929 3

Contract Overview

Balance:
0 DEV

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x1b27ec765e1e5bed7dd0f0f6c5b1b82f6375d0bc9ff4913d8b705113cbf60d14Execute(pending)2022-10-02 16:38:554 secs ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV(Pending)
0x6704fa5543cf51b487682c2ba13703bdeac46f2561294dc4c1736fc23b2889b7Execute29414452022-10-02 16:38:1247 secs ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523726
0x8ad7fc2b57e57c2087810226b6ee1e1cef083c5b55c28d709e3f2eac50f3886aExecute29414432022-10-02 16:37:421 min ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000653624
0x7675cea512d120261cd7f573469db700964623d14228df2b63665fc700c4a9f1Execute29414422022-10-02 16:37:181 min ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523894
0x9ac3bb01eb98390abcf7747d5b9fdd4dbd07422c54274736803105ce46ec1d44Execute29414412022-10-02 16:37:061 min ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.00052371
0xb8976b3727d9adccf07a1a752d4e40a2b4a0760ef7473683986a112bf407f891Execute29414302022-10-02 16:34:184 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523694
0xa86c24d0a77433c5d4b1796ad665f9ce4a23331bb01b7659ceaea74d6ba10e97Execute29414252022-10-02 16:33:185 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523942
0xc7f4ff78ccbfb51cab55b05fdb3b71fbae3c22911f7ff79be266e18c61423088Execute29414142022-10-02 16:30:428 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523798
0x485d0312497ab219f44077f545c6fda37dcf97558dd01adcf40f3dec3d585f6eExecute29414132022-10-02 16:30:308 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000653528
0x7fd63cbd217c1e04abc724b7d680417508f1630ce6731b0cadda35de44b2c2d2Execute29414032022-10-02 16:28:0010 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523734
0x0252de00769ec086ddd8c0d8b263fa93ac3cd259bd502ea1e189f55e2e704f8aExecute29414012022-10-02 16:27:2411 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523798
0x454097c24b83549aa75aa620874442f182505eaf321392f3127606b5a3da261fExecute29413992022-10-02 16:26:5412 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523782
0x19f5132dac52fa89f7002f31ab330aa58eb0eb0f3e5a388fc04fc8b0a60a7d2bExecute29413942022-10-02 16:25:3013 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.00052363
0x55cbdd93bb672f4bf29926841118e322350c6178452157c3c4a658d6e933b41dExecute29413872022-10-02 16:23:3015 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000522802
0x78949331ab9cc4c2cbdccdeda8956be108af5bacd5c3b32f78c68c0fe28a185fExecute29413852022-10-02 16:23:0615 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000522978
0x2e24f5db688b2b651fb940379f93537cac67efc732444022e754fc8bef3e8659Execute29413842022-10-02 16:22:5416 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.001111006
0x6742938b47b373b02719a2622eb966229ef6a1877f3ab0f31857fcd5ec51244fExecute29413832022-10-02 16:22:3016 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000523026
0x8f825b6578861d63bbecc2018bc55b06ae0c0608da0e4f9d1fb24a5591c30203Execute29413812022-10-02 16:21:5417 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000522954
0x0e49db9d277bb05507c04be8100865a99e935c08ccb8ea28ef9fb165cc6ec239Execute29413812022-10-02 16:21:5417 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000522858
0x3f2ffd328c6dc252ba6e5198ef08c3915ff62029218f7c2fd381c2cc29720345Execute29413782022-10-02 16:20:4218 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000522714
0x6d9e88c31149d5e0955fe52b76c8e3e47d2642b040f2c776f973177ac8b4e7ebExecute29413772022-10-02 16:20:3018 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000522778
0xf9166b1eec6c8ebd35940f05ae29eac7bfa862cda9e712a0877a3406447c099aExecute29413772022-10-02 16:20:3018 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.00052289
0x0d15a386ed1d80e5a5b0bc62f9d38f0a466d227069790dc64e8d2567d3e57baeExecute29413762022-10-02 16:19:0619 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000522802
0xce1cfc95fc8b09dab18975ff9bdf04d9b9aa8bd387402ee36593a06ce4f3ac1eExecute29413742022-10-02 16:18:4220 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.000522754
0x52ae4605f020a17b2bf58c5def982f03e8e9f054841988649b0746752435d53fExecute29413672022-10-02 16:17:0021 mins ago0xbe00c4312c97b1b13df330b1f44ea04d7886ecdb IN 0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV0.00052297
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x6f8688cdd3ca20fd92179604cecf46938f7654b4eaa0d407421847b7c9a0dbc729414332022-10-02 16:35:123 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x6f8688cdd3ca20fd92179604cecf46938f7654b4eaa0d407421847b7c9a0dbc729414332022-10-02 16:35:123 mins ago 0x20e57b30191c0865f1588533ac32ee7eb86ff11d0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0x6f8688cdd3ca20fd92179604cecf46938f7654b4eaa0d407421847b7c9a0dbc729414332022-10-02 16:35:123 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x6f8688cdd3ca20fd92179604cecf46938f7654b4eaa0d407421847b7c9a0dbc729414332022-10-02 16:35:123 mins ago 0x20e57b30191c0865f1588533ac32ee7eb86ff11d0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0xb8976b3727d9adccf07a1a752d4e40a2b4a0760ef7473683986a112bf407f89129414302022-10-02 16:34:184 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0xb8976b3727d9adccf07a1a752d4e40a2b4a0760ef7473683986a112bf407f89129414302022-10-02 16:34:184 mins ago 0x72f8a1a8acaaa806a52b64738327e6dbdfac7c250x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0xb8976b3727d9adccf07a1a752d4e40a2b4a0760ef7473683986a112bf407f89129414302022-10-02 16:34:184 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x8ec957289481417101199a2d467000a69c908ec45f58e4433cdf27975f3bff7b29414282022-10-02 16:33:545 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x8ec957289481417101199a2d467000a69c908ec45f58e4433cdf27975f3bff7b29414282022-10-02 16:33:545 mins ago 0x20e57b30191c0865f1588533ac32ee7eb86ff11d0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0x8ec957289481417101199a2d467000a69c908ec45f58e4433cdf27975f3bff7b29414282022-10-02 16:33:545 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x8ec957289481417101199a2d467000a69c908ec45f58e4433cdf27975f3bff7b29414282022-10-02 16:33:545 mins ago 0x20e57b30191c0865f1588533ac32ee7eb86ff11d0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0xa86c24d0a77433c5d4b1796ad665f9ce4a23331bb01b7659ceaea74d6ba10e9729414252022-10-02 16:33:185 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0xa86c24d0a77433c5d4b1796ad665f9ce4a23331bb01b7659ceaea74d6ba10e9729414252022-10-02 16:33:185 mins ago 0x72f8a1a8acaaa806a52b64738327e6dbdfac7c250x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0xa86c24d0a77433c5d4b1796ad665f9ce4a23331bb01b7659ceaea74d6ba10e9729414252022-10-02 16:33:185 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x9465c963276dae9120f73b8391dfba1d3c89830d3947af593bbb77b70cc53cdd29414172022-10-02 16:31:187 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x9465c963276dae9120f73b8391dfba1d3c89830d3947af593bbb77b70cc53cdd29414172022-10-02 16:31:187 mins ago 0x20e57b30191c0865f1588533ac32ee7eb86ff11d0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0x8cc444e1314fd87f790fd661ff0902595832813aba9b60ce8981b7b66bd235c929414162022-10-02 16:31:067 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x8cc444e1314fd87f790fd661ff0902595832813aba9b60ce8981b7b66bd235c929414162022-10-02 16:31:067 mins ago 0x20e57b30191c0865f1588533ac32ee7eb86ff11d0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0x01f38fcffcbbdf8d46a2d6911edd276006dc2620824844826e29d0d2461d653d29414162022-10-02 16:31:067 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x01f38fcffcbbdf8d46a2d6911edd276006dc2620824844826e29d0d2461d653d29414162022-10-02 16:31:067 mins ago 0x20e57b30191c0865f1588533ac32ee7eb86ff11d0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0x01f38fcffcbbdf8d46a2d6911edd276006dc2620824844826e29d0d2461d653d29414162022-10-02 16:31:067 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0x01f38fcffcbbdf8d46a2d6911edd276006dc2620824844826e29d0d2461d653d29414162022-10-02 16:31:067 mins ago 0x20e57b30191c0865f1588533ac32ee7eb86ff11d0x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0xc7f4ff78ccbfb51cab55b05fdb3b71fbae3c22911f7ff79be266e18c6142308829414142022-10-02 16:30:428 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
0xc7f4ff78ccbfb51cab55b05fdb3b71fbae3c22911f7ff79be266e18c6142308829414142022-10-02 16:30:428 mins ago 0x72f8a1a8acaaa806a52b64738327e6dbdfac7c250x5769d84dd62a6fd969856c75c7d321b84d4559290 DEV
0xc7f4ff78ccbfb51cab55b05fdb3b71fbae3c22911f7ff79be266e18c6142308829414142022-10-02 16:30:428 mins ago 0x5769d84dd62a6fd969856c75c7d321b84d4559290x72f8a1a8acaaa806a52b64738327e6dbdfac7c250 DEV
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AxelarGatewayProxyMultisig

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at moonbase.moonscan.io on 2022-08-01
*/

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

/**
 * @title EternalStorage
 * @dev This contract holds all the necessary state variables to carry out the storage of any contract.
 */
contract EternalStorage {
    mapping(bytes32 => uint256) private _uintStorage;
    mapping(bytes32 => string) private _stringStorage;
    mapping(bytes32 => address) private _addressStorage;
    mapping(bytes32 => bytes) private _bytesStorage;
    mapping(bytes32 => bool) private _boolStorage;
    mapping(bytes32 => int256) private _intStorage;

    // *** Getter Methods ***
    function getUint(bytes32 key) public view returns (uint256) {
        return _uintStorage[key];
    }

    function getString(bytes32 key) public view returns (string memory) {
        return _stringStorage[key];
    }

    function getAddress(bytes32 key) public view returns (address) {
        return _addressStorage[key];
    }

    function getBytes(bytes32 key) public view returns (bytes memory) {
        return _bytesStorage[key];
    }

    function getBool(bytes32 key) public view returns (bool) {
        return _boolStorage[key];
    }

    function getInt(bytes32 key) public view returns (int256) {
        return _intStorage[key];
    }

    // *** Setter Methods ***
    function _setUint(bytes32 key, uint256 value) internal {
        _uintStorage[key] = value;
    }

    function _setString(bytes32 key, string memory value) internal {
        _stringStorage[key] = value;
    }

    function _setAddress(bytes32 key, address value) internal {
        _addressStorage[key] = value;
    }

    function _setBytes(bytes32 key, bytes memory value) internal {
        _bytesStorage[key] = value;
    }

    function _setBool(bytes32 key, bool value) internal {
        _boolStorage[key] = value;
    }

    function _setInt(bytes32 key, int256 value) internal {
        _intStorage[key] = value;
    }

    // *** Delete Methods ***
    function _deleteUint(bytes32 key) internal {
        delete _uintStorage[key];
    }

    function _deleteString(bytes32 key) internal {
        delete _stringStorage[key];
    }

    function _deleteAddress(bytes32 key) internal {
        delete _addressStorage[key];
    }

    function _deleteBytes(bytes32 key) internal {
        delete _bytesStorage[key];
    }

    function _deleteBool(bytes32 key) internal {
        delete _boolStorage[key];
    }

    function _deleteInt(bytes32 key) internal {
        delete _intStorage[key];
    }
}


contract Burner {
    constructor(address tokenAddress, bytes32 salt) {
        BurnableMintableCappedERC20(tokenAddress).burn(salt);

        selfdestruct(payable(address(0)));
    }
}


abstract contract Ownable {
    address public owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    modifier onlyOwner() {
        require(owner == msg.sender, 'NOT_OWNER');
        _;
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), 'ZERO_ADDR');

        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}


interface IAxelarGateway {
    /**********\
    |* Events *|
    \**********/

    event Executed(bytes32 indexed commandId);

    event TokenDeployed(string symbol, address tokenAddresses);

    event TokenFrozen(string indexed symbol);

    event TokenUnfrozen(string indexed symbol);

    event AllTokensFrozen();

    event AllTokensUnfrozen();

    event AccountBlacklisted(address indexed account);

    event AccountWhitelisted(address indexed account);

    event Upgraded(address indexed implementation);

    /***********\
    |* Getters *|
    \***********/

    function allTokensFrozen() external view returns (bool);

    function implementation() external view returns (address);

    function tokenAddresses(string memory symbol) external view returns (address);

    function tokenFrozen(string memory symbol) external view returns (bool);

    function isCommandExecuted(bytes32 commandId) external view returns (bool);

    /*******************\
    |* Admin Functions *|
    \*******************/

    function freezeToken(string memory symbol) external;

    function unfreezeToken(string memory symbol) external;

    function freezeAllTokens() external;

    function unfreezeAllTokens() external;

    function upgrade(address newImplementation, bytes calldata setupParams) external;

    /**********************\
    |* External Functions *|
    \**********************/

    function setup(bytes calldata params) external;

    function execute(bytes calldata input) external;
}


contract AxelarGatewayProxy is EternalStorage {
    /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`.
    bytes32 internal constant KEY_IMPLEMENTATION =
        bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);

    fallback() external payable {
        address implementation = getAddress(KEY_IMPLEMENTATION);

        assembly {
            calldatacopy(0, 0, calldatasize())

            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            returndatacopy(0, 0, returndatasize())

            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    receive() external payable {
        revert('NO_ETHER');
    }
}


interface IAxelarGatewayMultisig is IAxelarGateway {

    event OwnershipTransferred(address[] preOwners, uint256 prevThreshold, address[] newOwners, uint256 newThreshold);

    event OperatorshipTransferred(address[] preOperators, uint256 prevThreshold, address[] newOperators, uint256 newThreshold);

    function owners() external view returns (address[] memory);

    function operators() external view returns (address[] memory);

}


/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address signer) {
        // Check the signature length
        require(signature.length == 65, 'INV_LEN');

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, 'INV_S');

        require(v == 27 || v == 28, 'INV_V');

        // If the signature is valid (and not malleable), return the signer address
        require((signer = ecrecover(hash, v, r, s)) != address(0), 'INV_SIG');
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
     * JSON-RPC method.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked('\x19Ethereum Signed Message:\n32', hash));
    }
}



/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}


/*
 * @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 GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return payable(msg.sender);
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}


/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    mapping(address => uint256) public override balanceOf;

    mapping(address => mapping(address => uint256)) public override allowance;

    uint256 public override totalSupply;

    string public name;
    string public symbol;

    uint8 public immutable decimals;

    /**
     * @dev Sets the values for {name}, {symbol}, and {decimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(
        string memory name_,
        string memory symbol_,
        uint8 decimals_
    ) {
        name = name_;
        symbol = symbol_;
        decimals = decimals_;
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), allowance[sender][_msgSender()] - amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, allowance[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, allowance[_msgSender()][spender] - subtractedValue);
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), 'ZERO_ADDR');
        require(recipient != address(0), 'ZERO_ADDR');

        _beforeTokenTransfer(sender, recipient, amount);

        balanceOf[sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), 'ZERO_ADDR');

        _beforeTokenTransfer(address(0), account, amount);

        totalSupply += amount;
        balanceOf[account] += amount;
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), 'ZERO_ADDR');

        _beforeTokenTransfer(account, address(0), amount);

        balanceOf[account] -= amount;
        totalSupply -= amount;
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), 'ZERO_ADDR');
        require(spender != address(0), 'ZERO_ADDR');

        allowance[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}


contract BurnableMintableCappedERC20 is ERC20, Ownable {
    uint256 public cap;

    bytes32 private constant PREFIX_TOKEN_FROZEN = keccak256('token-frozen');
    bytes32 private constant KEY_ALL_TOKENS_FROZEN = keccak256('all-tokens-frozen');

    event Frozen(address indexed owner);
    event Unfrozen(address indexed owner);

    constructor(
        string memory name,
        string memory symbol,
        uint8 decimals,
        uint256 capacity
    ) ERC20(name, symbol, decimals) Ownable() {
        cap = capacity;
    }

    function depositAddress(bytes32 salt) public view returns (address) {
        // This would be easier, cheaper, simpler, and result in  globally consistent deposit addresses for any salt (all chains, all tokens).
        // return address(uint160(uint256(keccak256(abi.encodePacked(bytes32(0x000000000000000000000000000000000000000000000000000000000000dead), salt)))));

        /* Convert a hash which is bytes32 to an address which is 20-byte long
        according to https://docs.soliditylang.org/en/v0.8.1/control-structures.html?highlight=create2#salted-contract-creations-create2 */
        return
            address(
                uint160(
                    uint256(
                        keccak256(
                            abi.encodePacked(
                                bytes1(0xff),
                                owner,
                                salt,
                                keccak256(abi.encodePacked(type(Burner).creationCode, abi.encode(address(this)), salt))
                            )
                        )
                    )
                )
            );
    }

    function mint(address account, uint256 amount) public onlyOwner {
        uint256 capacity = cap;
        require(capacity == 0 || totalSupply + amount <= capacity, 'CAP_EXCEEDED');

        _mint(account, amount);
    }

    function burn(bytes32 salt) public onlyOwner {
        address account = depositAddress(salt);
        _burn(account, balanceOf[account]);
    }

    function _beforeTokenTransfer(
        address,
        address,
        uint256
    ) internal view override {
        require(!EternalStorage(owner).getBool(KEY_ALL_TOKENS_FROZEN), 'IS_FROZEN');
        require(!EternalStorage(owner).getBool(keccak256(abi.encodePacked(PREFIX_TOKEN_FROZEN, symbol))), 'IS_FROZEN');
    }
}


contract AdminMultisigBase is EternalStorage {
    // AUDIT: slot names should be prefixed with some standard string
    // AUDIT: constants should be literal and their derivation should be in comments
    bytes32 internal constant KEY_ADMIN_EPOCH = keccak256('admin-epoch');

    bytes32 internal constant PREFIX_ADMIN = keccak256('admin');
    bytes32 internal constant PREFIX_ADMIN_COUNT = keccak256('admin-count');
    bytes32 internal constant PREFIX_ADMIN_THRESHOLD = keccak256('admin-threshold');
    bytes32 internal constant PREFIX_ADMIN_VOTE_COUNTS = keccak256('admin-vote-counts');
    bytes32 internal constant PREFIX_ADMIN_VOTED = keccak256('admin-voted');
    bytes32 internal constant PREFIX_IS_ADMIN = keccak256('is-admin');

    modifier onlyAdmin() {
        uint256 adminEpoch = _adminEpoch();

        require(_isAdmin(adminEpoch, msg.sender), 'NOT_ADMIN');

        bytes32 topic = keccak256(msg.data);

        // Check that admin has not voted, then record that they have voted.
        require(!_hasVoted(adminEpoch, topic, msg.sender), 'VOTED');
        _setHasVoted(adminEpoch, topic, msg.sender, true);

        // Determine the new vote count and update it.
        uint256 adminVoteCount = _getVoteCount(adminEpoch, topic) + uint256(1);
        _setVoteCount(adminEpoch, topic, adminVoteCount);

        // Do not proceed with operation execution if insufficient votes.
        if (adminVoteCount < _getAdminThreshold(adminEpoch)) return;

        _;

        // Clear vote count and voted booleans.
        _setVoteCount(adminEpoch, topic, uint256(0));

        uint256 adminCount = _getAdminCount(adminEpoch);

        for (uint256 i; i < adminCount; i++) {
            _setHasVoted(adminEpoch, topic, _getAdmin(adminEpoch, i), false);
        }
    }

    /********************\
    |* Pure Key Getters *|
    \********************/

    function _getAdminKey(uint256 adminEpoch, uint256 index) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_ADMIN, adminEpoch, index));
    }

    function _getAdminCountKey(uint256 adminEpoch) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_ADMIN_COUNT, adminEpoch));
    }

    function _getAdminThresholdKey(uint256 adminEpoch) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_ADMIN_THRESHOLD, adminEpoch));
    }

    function _getAdminVoteCountsKey(uint256 adminEpoch, bytes32 topic) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_ADMIN_VOTE_COUNTS, adminEpoch, topic));
    }

    function _getAdminVotedKey(
        uint256 adminEpoch,
        bytes32 topic,
        address account
    ) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_ADMIN_VOTED, adminEpoch, topic, account));
    }

    function _getIsAdminKey(uint256 adminEpoch, address account) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_IS_ADMIN, adminEpoch, account));
    }

    /***********\
    |* Getters *|
    \***********/

    function _adminEpoch() internal view returns (uint256) {
        return getUint(KEY_ADMIN_EPOCH);
    }

    function _getAdmin(uint256 adminEpoch, uint256 index) internal view returns (address) {
        return getAddress(_getAdminKey(adminEpoch, index));
    }

    function _getAdminCount(uint256 adminEpoch) internal view returns (uint256) {
        return getUint(_getAdminCountKey(adminEpoch));
    }

    function _getAdminThreshold(uint256 adminEpoch) internal view returns (uint256) {
        return getUint(_getAdminThresholdKey(adminEpoch));
    }

    function _getVoteCount(uint256 adminEpoch, bytes32 topic) internal view returns (uint256) {
        return getUint(_getAdminVoteCountsKey(adminEpoch, topic));
    }

    function _hasVoted(
        uint256 adminEpoch,
        bytes32 topic,
        address account
    ) internal view returns (bool) {
        return getBool(_getAdminVotedKey(adminEpoch, topic, account));
    }

    function _isAdmin(uint256 adminEpoch, address account) internal view returns (bool) {
        return getBool(_getIsAdminKey(adminEpoch, account));
    }

    /***********\
    |* Setters *|
    \***********/

    function _setAdminEpoch(uint256 adminEpoch) internal {
        _setUint(KEY_ADMIN_EPOCH, adminEpoch);
    }

    function _setAdmin(
        uint256 adminEpoch,
        uint256 index,
        address account
    ) internal {
        _setAddress(_getAdminKey(adminEpoch, index), account);
    }

    function _setAdminCount(uint256 adminEpoch, uint256 adminCount) internal {
        _setUint(_getAdminCountKey(adminEpoch), adminCount);
    }

    function _setAdmins(
        uint256 adminEpoch,
        address[] memory accounts,
        uint256 threshold
    ) internal {
        uint256 adminLength = accounts.length;

        require(adminLength >= threshold, 'INV_ADMINS');
        require(threshold > uint256(0), 'INV_ADMIN_THLD');

        _setAdminThreshold(adminEpoch, threshold);
        _setAdminCount(adminEpoch, adminLength);

        for (uint256 i; i < adminLength; i++) {
            address account = accounts[i];

            // Check that the account wasn't already set as an admin for this epoch.
            require(!_isAdmin(adminEpoch, account), 'DUP_ADMIN');

            // Set this account as the i-th admin in this epoch (needed to we can clear topic votes in `onlyAdmin`).
            _setAdmin(adminEpoch, i, account);
            _setIsAdmin(adminEpoch, account, true);
        }
    }

    function _setAdminThreshold(uint256 adminEpoch, uint256 adminThreshold) internal {
        _setUint(_getAdminThresholdKey(adminEpoch), adminThreshold);
    }

    function _setVoteCount(
        uint256 adminEpoch,
        bytes32 topic,
        uint256 voteCount
    ) internal {
        _setUint(_getAdminVoteCountsKey(adminEpoch, topic), voteCount);
    }

    function _setHasVoted(
        uint256 adminEpoch,
        bytes32 topic,
        address account,
        bool voted
    ) internal {
        _setBool(_getAdminVotedKey(adminEpoch, topic, account), voted);
    }

    function _setIsAdmin(
        uint256 adminEpoch,
        address account,
        bool isAdmin
    ) internal {
        _setBool(_getIsAdminKey(adminEpoch, account), isAdmin);
    }
}


abstract contract AxelarGateway is IAxelarGateway, AdminMultisigBase {
    /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`.
    bytes32 internal constant KEY_IMPLEMENTATION =
        bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);

    // AUDIT: slot names should be prefixed with some standard string
    // AUDIT: constants should be literal and their derivation should be in comments
    bytes32 internal constant KEY_ALL_TOKENS_FROZEN = keccak256('all-tokens-frozen');

    bytes32 internal constant PREFIX_COMMAND_EXECUTED = keccak256('command-executed');
    bytes32 internal constant PREFIX_TOKEN_ADDRESS = keccak256('token-address');
    bytes32 internal constant PREFIX_TOKEN_FROZEN = keccak256('token-frozen');

    bytes32 internal constant SELECTOR_BURN_TOKEN = keccak256('burnToken');
    bytes32 internal constant SELECTOR_DEPLOY_TOKEN = keccak256('deployToken');
    bytes32 internal constant SELECTOR_MINT_TOKEN = keccak256('mintToken');
    bytes32 internal constant SELECTOR_TRANSFER_OPERATORSHIP = keccak256('transferOperatorship');
    bytes32 internal constant SELECTOR_TRANSFER_OWNERSHIP = keccak256('transferOwnership');

    uint8 internal constant OLD_KEY_RETENTION = 16;

    modifier onlySelf() {
        require(msg.sender == address(this), 'NOT_SELF');

        _;
    }

    /***********\
    |* Getters *|
    \***********/

    function allTokensFrozen() public view override returns (bool) {
        return getBool(KEY_ALL_TOKENS_FROZEN);
    }

    function implementation() public view override returns (address) {
        return getAddress(KEY_IMPLEMENTATION);
    }

    function tokenAddresses(string memory symbol) public view override returns (address) {
        return getAddress(_getTokenAddressKey(symbol));
    }

    function tokenFrozen(string memory symbol) public view override returns (bool) {
        return getBool(_getFreezeTokenKey(symbol));
    }

    function isCommandExecuted(bytes32 commandId) public view override returns (bool) {
        return getBool(_getIsCommandExecutedKey(commandId));
    }

    /*******************\
    |* Admin Functions *|
    \*******************/

    function freezeToken(string memory symbol) external override onlyAdmin {
        _setBool(_getFreezeTokenKey(symbol), true);

        emit TokenFrozen(symbol);
    }

    function unfreezeToken(string memory symbol) external override onlyAdmin {
        _setBool(_getFreezeTokenKey(symbol), false);

        emit TokenUnfrozen(symbol);
    }

    function freezeAllTokens() external override onlyAdmin {
        _setBool(KEY_ALL_TOKENS_FROZEN, true);

        emit AllTokensFrozen();
    }

    function unfreezeAllTokens() external override onlyAdmin {
        _setBool(KEY_ALL_TOKENS_FROZEN, false);

        emit AllTokensUnfrozen();
    }

    function upgrade(address newImplementation, bytes calldata setupParams) external override onlyAdmin {
        emit Upgraded(newImplementation);

        // AUDIT: If `newImplementation.setup` performs `selfdestruct`, it will result in the loss of _this_ implementation (thereby losing the gateway)
        //        if `upgrade` is entered within the context of _this_ implementation itself.
        (bool success, ) = newImplementation.delegatecall(
            abi.encodeWithSelector(IAxelarGateway.setup.selector, setupParams)
        );
        require(success, 'SETUP_FAILED');

        _setImplementation(newImplementation);
    }

    /**********************\
    |* Internal Functions *|
    \**********************/

    function _deployToken(
        string memory name,
        string memory symbol,
        uint8 decimals,
        uint256 cap
    ) internal {
        require(tokenAddresses(symbol) == address(0), 'TOKEN_EXIST');

        bytes32 salt = keccak256(abi.encodePacked(symbol));
        address token = address(new BurnableMintableCappedERC20{ salt: salt }(name, symbol, decimals, cap));

        _setTokenAddress(symbol, token);

        emit TokenDeployed(symbol, token);
    }

    function _mintToken(
        string memory symbol,
        address account,
        uint256 amount
    ) internal {
        address tokenAddress = tokenAddresses(symbol);
        require(tokenAddress != address(0), 'TOKEN_NOT_EXIST');

        BurnableMintableCappedERC20(tokenAddress).mint(account, amount);
    }

    function _burnToken(string memory symbol, bytes32 salt) internal {
        address tokenAddress = tokenAddresses(symbol);
        require(tokenAddress != address(0), 'TOKEN_NOT_EXIST');

        BurnableMintableCappedERC20(tokenAddress).burn(salt);
    }

    /********************\
    |* Pure Key Getters *|
    \********************/

    function _getFreezeTokenKey(string memory symbol) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_TOKEN_FROZEN, symbol));
    }

    function _getTokenAddressKey(string memory symbol) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_TOKEN_ADDRESS, symbol));
    }

    function _getIsCommandExecutedKey(bytes32 commandId) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_COMMAND_EXECUTED, commandId));
    }

    /********************\
    |* Internal Getters *|
    \********************/

    function _getChainID() internal view returns (uint256 id) {
        assembly {
            id := chainid()
        }
    }

    /********************\
    |* Internal Setters *|
    \********************/

    function _setTokenAddress(string memory symbol, address tokenAddr) internal {
        _setAddress(_getTokenAddressKey(symbol), tokenAddr);
    }

    function _setCommandExecuted(bytes32 commandId, bool executed) internal {
        _setBool(_getIsCommandExecutedKey(commandId), executed);
    }

    function _setImplementation(address newImplementation) internal {
        _setAddress(KEY_IMPLEMENTATION, newImplementation);
    }
}


contract AxelarGatewayMultisig is IAxelarGatewayMultisig, AxelarGateway {
    // AUDIT: slot names should be prefixed with some standard string
    // AUDIT: constants should be literal and their derivation should be in comments
    bytes32 internal constant KEY_OWNER_EPOCH = keccak256('owner-epoch');

    bytes32 internal constant PREFIX_OWNER = keccak256('owner');
    bytes32 internal constant PREFIX_OWNER_COUNT = keccak256('owner-count');
    bytes32 internal constant PREFIX_OWNER_THRESHOLD = keccak256('owner-threshold');
    bytes32 internal constant PREFIX_IS_OWNER = keccak256('is-owner');

    bytes32 internal constant KEY_OPERATOR_EPOCH = keccak256('operator-epoch');

    bytes32 internal constant PREFIX_OPERATOR = keccak256('operator');
    bytes32 internal constant PREFIX_OPERATOR_COUNT = keccak256('operator-count');
    bytes32 internal constant PREFIX_OPERATOR_THRESHOLD = keccak256('operator-threshold');
    bytes32 internal constant PREFIX_IS_OPERATOR = keccak256('is-operator');

    function _containsDuplicates(address[] memory accounts) internal pure returns (bool) {
        uint256 count = accounts.length;

        for (uint256 i; i < count; ++i) {
            for (uint256 j = i + 1; j < count; ++j) {
                if (accounts[i] == accounts[j]) return true;
            }
        }

        return false;
    }

    /************************\
    |* Owners Functionality *|
    \************************/

    /********************\
    |* Pure Key Getters *|
    \********************/

    function _getOwnerKey(uint256 ownerEpoch, uint256 index) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_OWNER, ownerEpoch, index));
    }

    function _getOwnerCountKey(uint256 ownerEpoch) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_OWNER_COUNT, ownerEpoch));
    }

    function _getOwnerThresholdKey(uint256 ownerEpoch) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_OWNER_THRESHOLD, ownerEpoch));
    }

    function _getIsOwnerKey(uint256 ownerEpoch, address account) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_IS_OWNER, ownerEpoch, account));
    }

    /***********\
    |* Getters *|
    \***********/

    function _ownerEpoch() internal view returns (uint256) {
        return getUint(KEY_OWNER_EPOCH);
    }

    function _getOwner(uint256 ownerEpoch, uint256 index) internal view returns (address) {
        return getAddress(_getOwnerKey(ownerEpoch, index));
    }

    function _getOwnerCount(uint256 ownerEpoch) internal view returns (uint256) {
        return getUint(_getOwnerCountKey(ownerEpoch));
    }

    function _getOwnerThreshold(uint256 ownerEpoch) internal view returns (uint256) {
        return getUint(_getOwnerThresholdKey(ownerEpoch));
    }

    function _isOwner(uint256 ownerEpoch, address account) internal view returns (bool) {
        return getBool(_getIsOwnerKey(ownerEpoch, account));
    }

    /// @dev Returns true if a sufficient quantity of `accounts` are owners in the same `ownerEpoch`, within the last `OLD_KEY_RETENTION + 1` owner epochs.
    function _areValidRecentOwners(address[] memory accounts) internal view returns (bool) {
        uint256 ownerEpoch = _ownerEpoch();
        uint256 recentEpochs = OLD_KEY_RETENTION + uint256(1);
        uint256 lowerBoundOwnerEpoch = ownerEpoch > recentEpochs ? ownerEpoch - recentEpochs : uint256(0);

        while (ownerEpoch > lowerBoundOwnerEpoch) {
            if (_areValidOwnersInEpoch(ownerEpoch--, accounts)) return true;
        }

        return false;
    }

    /// @dev Returns true if a sufficient quantity of `accounts` are owners in the `ownerEpoch`.
    function _areValidOwnersInEpoch(uint256 ownerEpoch, address[] memory accounts) internal view returns (bool) {
        if (_containsDuplicates(accounts)) return false;

        uint256 threshold = _getOwnerThreshold(ownerEpoch);
        uint256 validSignerCount;

        for (uint256 i; i < accounts.length; i++) {
            if (_isOwner(ownerEpoch, accounts[i]) && ++validSignerCount >= threshold) return true;
        }

        return false;
    }

    /// @dev Returns the array of owners within the current `ownerEpoch`.
    function owners() public view override returns (address[] memory results) {
        uint256 ownerEpoch = _ownerEpoch();
        uint256 ownerCount = _getOwnerCount(ownerEpoch);
        results = new address[](ownerCount);

        for (uint256 i; i < ownerCount; i++) {
            results[i] = _getOwner(ownerEpoch, i);
        }
    }

    /***********\
    |* Setters *|
    \***********/

    function _setOwnerEpoch(uint256 ownerEpoch) internal {
        _setUint(KEY_OWNER_EPOCH, ownerEpoch);
    }

    function _setOwner(
        uint256 ownerEpoch,
        uint256 index,
        address account
    ) internal {
        require(account != address(0), 'ZERO_ADDR');
        _setAddress(_getOwnerKey(ownerEpoch, index), account);
    }

    function _setOwnerCount(uint256 ownerEpoch, uint256 ownerCount) internal {
        _setUint(_getOwnerCountKey(ownerEpoch), ownerCount);
    }

    function _setOwners(
        uint256 ownerEpoch,
        address[] memory accounts,
        uint256 threshold
    ) internal {
        uint256 accountLength = accounts.length;

        require(accountLength >= threshold, 'INV_OWNERS');
        require(threshold > uint256(0), 'INV_OWNER_THLD');

        _setOwnerThreshold(ownerEpoch, threshold);
        _setOwnerCount(ownerEpoch, accountLength);

        for (uint256 i; i < accountLength; i++) {
            address account = accounts[i];

            // Check that the account wasn't already set as an owner for this ownerEpoch.
            require(!_isOwner(ownerEpoch, account), 'DUP_OWNER');

            // Set this account as the i-th owner in this ownerEpoch (needed to we can get all the owners for `owners`).
            _setOwner(ownerEpoch, i, account);
            _setIsOwner(ownerEpoch, account, true);
        }
    }

    function _setOwnerThreshold(uint256 ownerEpoch, uint256 ownerThreshold) internal {
        _setUint(_getOwnerThresholdKey(ownerEpoch), ownerThreshold);
    }

    function _setIsOwner(
        uint256 ownerEpoch,
        address account,
        bool isOwner
    ) internal {
        _setBool(_getIsOwnerKey(ownerEpoch, account), isOwner);
    }

    /**************************\
    |* Operator Functionality *|
    \**************************/

    /********************\
    |* Pure Key Getters *|
    \********************/

    function _getOperatorKey(uint256 operatorEpoch, uint256 index) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_OPERATOR, operatorEpoch, index));
    }

    function _getOperatorCountKey(uint256 operatorEpoch) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_OPERATOR_COUNT, operatorEpoch));
    }

    function _getOperatorThresholdKey(uint256 operatorEpoch) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_OPERATOR_THRESHOLD, operatorEpoch));
    }

    function _getIsOperatorKey(uint256 operatorEpoch, address account) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(PREFIX_IS_OPERATOR, operatorEpoch, account));
    }

    /***********\
    |* Getters *|
    \***********/

    function _operatorEpoch() internal view returns (uint256) {
        return getUint(KEY_OPERATOR_EPOCH);
    }

    function _getOperator(uint256 operatorEpoch, uint256 index) internal view returns (address) {
        return getAddress(_getOperatorKey(operatorEpoch, index));
    }

    function _getOperatorCount(uint256 operatorEpoch) internal view returns (uint256) {
        return getUint(_getOperatorCountKey(operatorEpoch));
    }

    function _getOperatorThreshold(uint256 operatorEpoch) internal view returns (uint256) {
        return getUint(_getOperatorThresholdKey(operatorEpoch));
    }

    function _isOperator(uint256 operatorEpoch, address account) internal view returns (bool) {
        return getBool(_getIsOperatorKey(operatorEpoch, account));
    }

    /// @dev Returns true if a sufficient quantity of `accounts` are operator in the same `operatorEpoch`, within the last `OLD_KEY_RETENTION + 1` operator epochs.
    function _areValidRecentOperators(address[] memory accounts) internal view returns (bool) {
        uint256 operatorEpoch = _operatorEpoch();
        uint256 recentEpochs = OLD_KEY_RETENTION + uint256(1);
        uint256 lowerBoundOperatorEpoch = operatorEpoch > recentEpochs ? operatorEpoch - recentEpochs : uint256(0);

        while (operatorEpoch > lowerBoundOperatorEpoch) {
            if (_areValidOperatorsInEpoch(operatorEpoch--, accounts)) return true;
        }

        return false;
    }

    /// @dev Returns true if a sufficient quantity of `accounts` are operator in the `operatorEpoch`.
    function _areValidOperatorsInEpoch(uint256 operatorEpoch, address[] memory accounts) internal view returns (bool) {
        if (_containsDuplicates(accounts)) return false;

        uint256 threshold = _getOperatorThreshold(operatorEpoch);
        uint256 validSignerCount;

        for (uint256 i; i < accounts.length; i++) {
            if (_isOperator(operatorEpoch, accounts[i]) && ++validSignerCount >= threshold) return true;
        }

        return false;
    }

    /// @dev Returns the array of operators within the current `operatorEpoch`.
    function operators() public view override returns (address[] memory results) {
        uint256 operatorEpoch = _operatorEpoch();
        uint256 operatorCount = _getOperatorCount(operatorEpoch);
        results = new address[](operatorCount);

        for (uint256 i; i < operatorCount; i++) {
            results[i] = _getOperator(operatorEpoch, i);
        }
    }

    /***********\
    |* Setters *|
    \***********/

    function _setOperatorEpoch(uint256 operatorEpoch) internal {
        _setUint(KEY_OPERATOR_EPOCH, operatorEpoch);
    }

    function _setOperator(
        uint256 operatorEpoch,
        uint256 index,
        address account
    ) internal {
        // AUDIT: Should have `require(account != address(0), 'ZERO_ADDR');` like Singlesig?
        _setAddress(_getOperatorKey(operatorEpoch, index), account);
    }

    function _setOperatorCount(uint256 operatorEpoch, uint256 operatorCount) internal {
        _setUint(_getOperatorCountKey(operatorEpoch), operatorCount);
    }

    function _setOperators(
        uint256 operatorEpoch,
        address[] memory accounts,
        uint256 threshold
    ) internal {
        uint256 accountLength = accounts.length;

        require(accountLength >= threshold, 'INV_OPERATORS');
        require(threshold > uint256(0), 'INV_OPERATOR_THLD');

        _setOperatorThreshold(operatorEpoch, threshold);
        _setOperatorCount(operatorEpoch, accountLength);

        for (uint256 i; i < accountLength; i++) {
            address account = accounts[i];

            // Check that the account wasn't already set as an operator for this operatorEpoch.
            require(!_isOperator(operatorEpoch, account), 'DUP_OPERATOR');

            // Set this account as the i-th operator in this operatorEpoch (needed to we can get all the operators for `operators`).
            _setOperator(operatorEpoch, i, account);
            _setIsOperator(operatorEpoch, account, true);
        }
    }

    function _setOperatorThreshold(uint256 operatorEpoch, uint256 operatorThreshold) internal {
        _setUint(_getOperatorThresholdKey(operatorEpoch), operatorThreshold);
    }

    function _setIsOperator(
        uint256 operatorEpoch,
        address account,
        bool isOperator
    ) internal {
        _setBool(_getIsOperatorKey(operatorEpoch, account), isOperator);
    }

    /**********************\
    |* Self Functionality *|
    \**********************/

    function deployToken(bytes calldata params) external onlySelf {
        (string memory name, string memory symbol, uint8 decimals, uint256 cap) = abi.decode(
            params,
            (string, string, uint8, uint256)
        );

        _deployToken(name, symbol, decimals, cap);
    }

    function mintToken(bytes calldata params) external onlySelf {
        (string memory symbol, address account, uint256 amount) = abi.decode(params, (string, address, uint256));

        _mintToken(symbol, account, amount);
    }

    function burnToken(bytes calldata params) external onlySelf {
        (string memory symbol, bytes32 salt) = abi.decode(params, (string, bytes32));

        _burnToken(symbol, salt);
    }

    function transferOwnership(bytes calldata params) external onlySelf {
        (address[] memory newOwners, uint256 newThreshold) = abi.decode(params, (address[], uint256));

        uint256 ownerEpoch = _ownerEpoch();

        emit OwnershipTransferred(owners(), _getOwnerThreshold(ownerEpoch), newOwners, newThreshold);

        _setOwnerEpoch(++ownerEpoch);
        _setOwners(ownerEpoch, newOwners, newThreshold);
    }

    function transferOperatorship(bytes calldata params) external onlySelf {
        (address[] memory newOperators, uint256 newThreshold) = abi.decode(params, (address[], uint256));

        uint256 ownerEpoch = _ownerEpoch();

        emit OperatorshipTransferred(operators(), _getOperatorThreshold(ownerEpoch), newOperators, newThreshold);

        uint256 operatorEpoch = _operatorEpoch();
        _setOperatorEpoch(++operatorEpoch);
        _setOperators(operatorEpoch, newOperators, newThreshold);
    }

    /**************************\
    |* External Functionality *|
    \**************************/

    function setup(bytes calldata params) external override {
        // Prevent setup from being called on a non-proxy (the implementation).
        require(implementation() != address(0), 'NOT_PROXY');

        (
            address[] memory adminAddresses,
            uint256 adminThreshold,
            address[] memory ownerAddresses,
            uint256 ownerThreshold,
            address[] memory operatorAddresses,
            uint256 operatorThreshold
        ) = abi.decode(params, (address[], uint256, address[], uint256, address[], uint256));

        uint256 adminEpoch = _adminEpoch() + uint256(1);
        _setAdminEpoch(adminEpoch);
        _setAdmins(adminEpoch, adminAddresses, adminThreshold);

        uint256 ownerEpoch = _ownerEpoch() + uint256(1);
        _setOwnerEpoch(ownerEpoch);
        _setOwners(ownerEpoch, ownerAddresses, ownerThreshold);

        uint256 operatorEpoch = _operatorEpoch() + uint256(1);
        _setOperatorEpoch(operatorEpoch);
        _setOperators(operatorEpoch, operatorAddresses, operatorThreshold);

        emit OwnershipTransferred(new address[](uint256(0)), uint256(0), ownerAddresses, ownerThreshold);
        emit OperatorshipTransferred(new address[](uint256(0)), uint256(0), operatorAddresses, operatorThreshold);
    }

    function execute(bytes calldata input) external override {
        (bytes memory data, bytes[] memory signatures) = abi.decode(input, (bytes, bytes[]));

        _execute(data, signatures);
    }

    function _execute(bytes memory data, bytes[] memory signatures) internal {
        uint256 signatureCount = signatures.length;

        address[] memory signers = new address[](signatureCount);

        for (uint256 i; i < signatureCount; i++) {
            signers[i] = ECDSA.recover(ECDSA.toEthSignedMessageHash(keccak256(data)), signatures[i]);
        }

        (uint256 chainId, bytes32[] memory commandIds, string[] memory commands, bytes[] memory params) = abi.decode(
            data,
            (uint256, bytes32[], string[], bytes[])
        );

        require(chainId == _getChainID(), 'INV_CHAIN');

        uint256 commandsLength = commandIds.length;

        require(commandsLength == commands.length && commandsLength == params.length, 'INV_CMDS');

        bool areValidCurrentOwners = _areValidOwnersInEpoch(_ownerEpoch(), signers);
        bool areValidRecentOwners = areValidCurrentOwners || _areValidRecentOwners(signers);
        bool areValidRecentOperators = _areValidRecentOperators(signers);

        for (uint256 i; i < commandsLength; i++) {
            bytes32 commandId = commandIds[i];

            if (isCommandExecuted(commandId)) continue; /* Ignore if duplicate commandId received */

            bytes4 commandSelector;
            bytes32 commandHash = keccak256(abi.encodePacked(commands[i]));

            if (commandHash == SELECTOR_DEPLOY_TOKEN) {
                if (!areValidRecentOwners) continue;

                commandSelector = AxelarGatewayMultisig.deployToken.selector;
            } else if (commandHash == SELECTOR_MINT_TOKEN) {
                if (!areValidRecentOperators && !areValidRecentOwners) continue;

                commandSelector = AxelarGatewayMultisig.mintToken.selector;
            } else if (commandHash == SELECTOR_BURN_TOKEN) {
                if (!areValidRecentOperators && !areValidRecentOwners) continue;

                commandSelector = AxelarGatewayMultisig.burnToken.selector;
            } else if (commandHash == SELECTOR_TRANSFER_OWNERSHIP) {
                if (!areValidCurrentOwners) continue;

                commandSelector = AxelarGatewayMultisig.transferOwnership.selector;
            } else if (commandHash == SELECTOR_TRANSFER_OPERATORSHIP) {
                if (!areValidCurrentOwners) continue;

                commandSelector = AxelarGatewayMultisig.transferOperatorship.selector;
            } else {
                continue; /* Ignore if unknown command received */
            }

            // Prevent a re-entrancy from executing this command before it can be marked as successful.
            _setCommandExecuted(commandId, true);
            (bool success, ) = address(this).call(abi.encodeWithSelector(commandSelector, params[i]));
            _setCommandExecuted(commandId, success);

            if (success) {
                emit Executed(commandId);
            }
        }
    }
}


contract AxelarGatewayProxyMultisig is AxelarGatewayProxy {
    constructor(bytes memory params) {
        // AUDIT: constructor contains entire AxelarGatewayMultisig bytecode. Consider passing in an AxelarGatewayMultisig address.
        address gateway = address(new AxelarGatewayMultisig());

        _setAddress(KEY_IMPLEMENTATION, gateway);

        (bool success, ) = gateway.delegatecall(abi.encodeWithSelector(IAxelarGateway.setup.selector, params));
        require(success, 'SETUP_FAILED');
    }

    function setup(bytes calldata params) external {}
}

Contract ABI

[{"inputs":[{"internalType":"bytes","name":"params","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"getAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"getBool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"getBytes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"getInt","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"getString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"getUint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"params","type":"bytes"}],"name":"setup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b5060405161541638038061541683398101604081905261002f91610201565b600060405161003d906101ae565b604051809103906000f080158015610059573d6000803e3d6000fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60005260026020527f11141f466c69fd409e1990e063b49cd6d61ed2ecff27a2e402e259ca6b9a01a380546001600160a01b0319166001600160a01b03831617905590506000816001600160a01b0316639ded06df60e01b846040516024016100e491906102ad565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161012291906102e0565b600060405180830381855af49150503d806000811461015d576040519150601f19603f3d011682016040523d82523d6000602084013e610162565b606091505b50509050806101a65760405162461bcd60e51b815260206004820152600c60248201526b14d155155417d1905253115160a21b604482015260640160405180910390fd5b5050506102fc565b614c56806107c083390190565b634e487b7160e01b600052604160045260246000fd5b60005b838110156101ec5781810151838201526020016101d4565b838111156101fb576000848401525b50505050565b60006020828403121561021357600080fd5b81516001600160401b038082111561022a57600080fd5b818401915084601f83011261023e57600080fd5b815181811115610250576102506101bb565b604051601f8201601f19908116603f01168101908382118183101715610278576102786101bb565b8160405282815287602084870101111561029157600080fd5b6102a28360208301602088016101d1565b979650505050505050565b60208152600082518060208401526102cc8160408501602087016101d1565b601f01601f19169190910160400192915050565b600082516102f28184602087016101d1565b9190910192915050565b6104b58061030b6000396000f3fe6080604052600436106100745760003560e01c80639ded06df1161004e5780639ded06df146101ea578063bd02d0f51461020b578063c031a18014610246578063dc97d96214610266576100b0565b806321f8a7211461012a5780637ae1cfca1461017d578063986e791a146101bd576100b0565b366100b05760405162461bcd60e51b81526020600482015260086024820152672727afa2aa2422a960c11b604482015260640160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600090815260026020527f11141f466c69fd409e1990e063b49cd6d61ed2ecff27a2e402e259ca6b9a01a3546001600160a01b03169036908037600080366000845af43d6000803e808015610125573d6000f35b3d6000fd5b34801561013657600080fd5b50610160610145366004610352565b6000908152600260205260409020546001600160a01b031690565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561018957600080fd5b506101ad610198366004610352565b60009081526004602052604090205460ff1690565b6040519015158152602001610174565b3480156101c957600080fd5b506101dd6101d8366004610352565b610293565b60405161017491906103b8565b3480156101f657600080fd5b506102096102053660046103d2565b5050565b005b34801561021757600080fd5b50610238610226366004610352565b60009081526020819052604090205490565b604051908152602001610174565b34801561025257600080fd5b506101dd610261366004610352565b610335565b34801561027257600080fd5b50610238610281366004610352565b60009081526005602052604090205490565b60008181526001602052604090208054606091906102b090610444565b80601f01602080910402602001604051908101604052809291908181526020018280546102dc90610444565b80156103295780601f106102fe57610100808354040283529160200191610329565b820191906000526020600020905b81548152906001019060200180831161030c57829003601f168201915b50505050509050919050565b60008181526003602052604090208054606091906102b090610444565b60006020828403121561036457600080fd5b5035919050565b6000815180845260005b8181101561039157602081850181015186830182015201610375565b818111156103a3576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006103cb602083018461036b565b9392505050565b600080602083850312156103e557600080fd5b823567ffffffffffffffff808211156103fd57600080fd5b818501915085601f83011261041157600080fd5b81358181111561042057600080fd5b86602082850101111561043257600080fd5b60209290920196919550909350505050565b600181811c9082168061045857607f821691505b6020821081141561047957634e487b7160e01b600052602260045260246000fd5b5091905056fea2646970667358221220de895ffe962788e1214df4d87d6cb2898ccd094eda688dc0ec9f1c9eabb1415064736f6c63430008090033608060405234801561001057600080fd5b50614c36806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620001925760003560e01c80639ded06df11620000f0578063d1cf834f11620000a3578063d2bc37f8116200007a578063d2bc37f8146200042a578063dc97d9621462000434578063e3dfa2991462000457578063e673df8a146200046157600080fd5b8063d1cf834f14620003e5578063d26ff21014620003fc578063d289d1cb146200041357600080fd5b80639ded06df1462000301578063aa1e1f0a1462000318578063affe39c1146200036c578063bd02d0f51462000385578063c031a18014620003b7578063c987336c14620003ce57600080fd5b806360c6ff43116200014957806360c6ff431462000248578063646c5d34146200025f5780637ae1cfca14620002765780637b1b769e14620002ad578063935b13f614620002c4578063986e791a14620002db57600080fd5b8063037699c1146200019757806309c5eabe14620001b057806321f8a72114620001c757806334ff698314620002105780633cd6ee6d14620002275780635c60da1b146200023e575b600080fd5b620001ae620001a836600462002dd9565b6200046b565b005b620001ae620001c136600462002dd9565b620004bd565b620001f3620001d836600462002e1e565b6000908152600260205260409020546001600160a01b031690565b6040516001600160a01b0390911681526020015b60405180910390f35b620001ae6200022136600462002f07565b620004de565b620001ae6200023836600462002dd9565b6200066c565b620001f3620006b7565b620001ae6200025936600462002dd9565b6200070e565b620001ae6200027036600462002f07565b6200075c565b6200029c6200028736600462002e1e565b60009081526004602052604090205460ff1690565b604051901515815260200162000207565b6200029c620002be36600462002f07565b620008da565b620001f3620002d536600462002f07565b620008f1565b620002f2620002ec36600462002e1e565b62000902565b60405162000207919062002f9c565b620001ae6200031236600462002dd9565b620009ac565b7f75a31d1ce8e5f9892188befc328d3b9bd3fa5037457e881abc21f388471b8d9660005260046020527fa0b596b8942d6ef5cc77ce0ad89a75f0bfcc7f0132cd8db58e8449dcf04a858a5460ff166200029c565b6200037662000ba6565b60405162000207919062002ff7565b620003a86200039636600462002e1e565b60009081526020819052604090205490565b60405190815260200162000207565b620002f2620003c836600462002e1e565b62000c6d565b620001ae620003df36600462003022565b62000c8c565b620001ae620003f636600462002dd9565b62000eec565b6200029c6200040d36600462002e1e565b62000fa8565b620001ae6200042436600462002dd9565b62000fb9565b620001ae62001083565b620003a86200044536600462002e1e565b60009081526005602052604090205490565b620001ae620011ff565b620003766200137b565b333014620004965760405162461bcd60e51b81526004016200048d906200307c565b60405180910390fd5b600080620004a7838501856200309e565b91509150620004b782826200143c565b50505050565b600080620004ce838501856200310c565b91509150620004b78282620014f6565b6000620004ea62001a10565b9050620004f8813362001a5e565b620005175760405162461bcd60e51b81526004016200048d90620031ef565b600080366040516200052b92919062003212565b604051809103902090506200054282823362001a77565b15620005625760405162461bcd60e51b81526004016200048d9062003222565b62000571828233600162001a92565b6000600162000581848462001aaa565b6200058d919062003257565b90506200059c83838362001abc565b620005a78362001ae4565b811015620005b55750505050565b620005cc620005c48562001af5565b600062001b49565b83604051620005dc919062003272565b604051908190038120907f5327e3af9cd2d5c19a8dff23ef487d7a4d5f6fc985464f1792a33c212057598990600090a26200061a8383600062001abc565b6000620006278462001b69565b905060005b8181101562000664576200064f858562000647888562001b7a565b600062001a92565b806200065b8162003290565b9150506200062c565b505050505050565b3330146200068e5760405162461bcd60e51b81526004016200048d906200307c565b6000808080620006a185870187620032ae565b9350935093509350620006648484848462001b8c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60005260026020527f11141f466c69fd409e1990e063b49cd6d61ed2ecff27a2e402e259ca6b9a01a3546001600160a01b031690565b333014620007305760405162461bcd60e51b81526004016200048d906200307c565b60008080620007428486018662003339565b9250925092506200075583838362001ca3565b5050505050565b60006200076862001a10565b905062000776813362001a5e565b620007955760405162461bcd60e51b81526004016200048d90620031ef565b60008036604051620007a992919062003212565b60405180910390209050620007c082823362001a77565b15620007e05760405162461bcd60e51b81526004016200048d9062003222565b620007ef828233600162001a92565b60006001620007ff848462001aaa565b6200080b919062003257565b90506200081a83838362001abc565b620008258362001ae4565b811015620008335750505050565b6200084a620008428562001af5565b600162001b49565b836040516200085a919062003272565b604051908190038120907f11260c92ecb021c33706db3a9699410f343d5f2175201a4551fe7634347a0cf190600090a2620008988383600062001abc565b6000620008a58462001b69565b905060005b818110156200066457620008c5858562000647888562001b7a565b80620008d18162003290565b915050620008aa565b6000620008eb620002878362001af5565b92915050565b6000620008eb620001d88362001d5c565b6000818152600160205260409020805460609190620009219062003398565b80601f01602080910402602001604051908101604052809291908181526020018280546200094f9062003398565b8015620009a05780601f106200097457610100808354040283529160200191620009a0565b820191906000526020600020905b8154815290600101906020018083116200098257829003601f168201915b50505050509050919050565b6000620009b8620006b7565b6001600160a01b03161415620009fd5760405162461bcd60e51b81526020600482015260096024820152684e4f545f50524f585960b81b60448201526064016200048d565b6000808080808062000a12878901896200344d565b9550955095509550955095506000600162000a2c62001a10565b62000a38919062003257565b905062000a8c817fd51dc9b187568bb94760866e1d0d066ca470037d2d331afb1a02ec74bfb8990c60009081526020527ff8d0c05cd32e3272241fdc9d5839565f8bcf94139cb4bd09e230e1b57a60ddc255565b62000a9981888862001d96565b6000600162000aa762001ed7565b62000ab3919062003257565b905062000ac08162001f25565b62000acd81878762001f72565b6000600162000adb620020b3565b62000ae7919062003257565b905062000af48162002101565b62000b018186866200214e565b60408051600080825260208201928390527fd167b96814cd24898418cc293e8d47d54afe6dcf0631283f0830e1eae621f6bd9262000b459291908b908b90620034fa565b60405180910390a160408051600080825260208201928390527fe7475da747ead33c03118a4b2cca5e521e930dd8ddc556751fe12d1e8395db2c9262000b9192919089908990620034fa565b60405180910390a15050505050505050505050565b6060600062000bb462001ed7565b9050600062000bc38262002298565b9050806001600160401b0381111562000be05762000be062002e38565b60405190808252806020026020018201604052801562000c0a578160200160208202803683370190505b50925060005b8181101562000c675762000c258382620022a9565b84828151811062000c3a5762000c3a6200353b565b6001600160a01b03909216602092830291909101909101528062000c5e8162003290565b91505062000c10565b50505090565b6000818152600360205260409020805460609190620009219062003398565b600062000c9862001a10565b905062000ca6813362001a5e565b62000cc55760405162461bcd60e51b81526004016200048d90620031ef565b6000803660405162000cd992919062003212565b6040518091039020905062000cf082823362001a77565b1562000d105760405162461bcd60e51b81526004016200048d9062003222565b62000d1f828233600162001a92565b6000600162000d2f848462001aaa565b62000d3b919062003257565b905062000d4a83838362001abc565b62000d558362001ae4565b81101562000d6557505050505050565b6040516001600160a01b038716907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a26000866001600160a01b0316639ded06df60e01b878760405160240162000dc292919062003551565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905162000e02919062003272565b600060405180830381855af49150503d806000811462000e3f576040519150601f19603f3d011682016040523d82523d6000602084013e62000e44565b606091505b505090508062000e865760405162461bcd60e51b815260206004820152600c60248201526b14d155155417d1905253115160a21b60448201526064016200048d565b62000e9187620022bb565b5062000ea08383600062001abc565b600062000ead8462001b69565b905060005b8181101562000ee25762000ecd858562000647888562001b7a565b8062000ed98162003290565b91505062000eb2565b5050505050505050565b33301462000f0e5760405162461bcd60e51b81526004016200048d906200307c565b60008062000f1f8385018562003580565b91509150600062000f2f62001ed7565b90507fd167b96814cd24898418cc293e8d47d54afe6dcf0631283f0830e1eae621f6bd62000f5c62000ba6565b62000f6783620022e7565b858560405162000f7b9493929190620034fa565b60405180910390a162000f9b62000f928262003290565b91508162001f25565b6200075581848462001f72565b6000620008eb6200028783620022f8565b33301462000fdb5760405162461bcd60e51b81526004016200048d906200307c565b60008062000fec8385018562003580565b91509150600062000ffc62001ed7565b90507fe7475da747ead33c03118a4b2cca5e521e930dd8ddc556751fe12d1e8395db2c620010296200137b565b620010348362002334565b8585604051620010489493929190620034fa565b60405180910390a160006200105c620020b3565b9050620010766200106d8262003290565b91508162002101565b620006648185856200214e565b60006200108f62001a10565b90506200109d813362001a5e565b620010bc5760405162461bcd60e51b81526004016200048d90620031ef565b60008036604051620010d092919062003212565b60405180910390209050620010e782823362001a77565b15620011075760405162461bcd60e51b81526004016200048d9062003222565b62001116828233600162001a92565b6000600162001126848462001aaa565b62001132919062003257565b90506200114183838362001abc565b6200114c8362001ae4565b8110156200115957505050565b620011867f75a31d1ce8e5f9892188befc328d3b9bd3fa5037457e881abc21f388471b8d96600162001b49565b6040517f9f428b56ca209118783db391e8a5a62827b6b218add33411061060d308af6ead90600090a1620011bd8383600062001abc565b6000620011ca8462001b69565b905060005b818110156200075557620011ea858562000647888562001b7a565b80620011f68162003290565b915050620011cf565b60006200120b62001a10565b905062001219813362001a5e565b620012385760405162461bcd60e51b81526004016200048d90620031ef565b600080366040516200124c92919062003212565b604051809103902090506200126382823362001a77565b15620012835760405162461bcd60e51b81526004016200048d9062003222565b62001292828233600162001a92565b60006001620012a2848462001aaa565b620012ae919062003257565b9050620012bd83838362001abc565b620012c88362001ae4565b811015620012d557505050565b620013027f75a31d1ce8e5f9892188befc328d3b9bd3fa5037457e881abc21f388471b8d96600062001b49565b6040517f0e821ff109470f6aa1aebb161aa0e7328b1a8552aa48e09ed2d03184ecece9a690600090a1620013398383600062001abc565b6000620013468462001b69565b905060005b81811015620007555762001366858562000647888562001b7a565b80620013728162003290565b9150506200134b565b6060600062001389620020b3565b90506000620013988262002345565b9050806001600160401b03811115620013b557620013b562002e38565b604051908082528060200260200182016040528015620013df578160200160208202803683370190505b50925060005b8181101562000c6757620013fa838262002356565b8482815181106200140f576200140f6200353b565b6001600160a01b039092166020928302919091019091015280620014338162003290565b915050620013e5565b60006200144983620008f1565b90506001600160a01b038116620014955760405162461bcd60e51b815260206004820152600f60248201526e1513d2d15397d393d517d1561254d5608a1b60448201526064016200048d565b6040516308a1eee160e01b8152600481018390526001600160a01b038216906308a1eee190602401600060405180830381600087803b158015620014d857600080fd5b505af1158015620014ed573d6000803e3d6000fd5b50505050505050565b80516000816001600160401b0381111562001515576200151562002e38565b6040519080825280602002602001820160405280156200153f578160200160208202803683370190505b50905060005b82811015620015c9576200158762001564868051906020012062002368565b8583815181106200157957620015796200353b565b6020026020010151620023a4565b8282815181106200159c576200159c6200353b565b6001600160a01b039092166020928302919091019091015280620015c08162003290565b91505062001545565b5060008060008087806020019051810190620015e691906200372d565b9350935093509350620015f64690565b8414620016325760405162461bcd60e51b815260206004820152600960248201526824a72b2fa1a420a4a760b91b60448201526064016200048d565b8251825181148015620016455750815181145b6200167e5760405162461bcd60e51b8152602060048201526008602482015267494e565f434d445360c01b60448201526064016200048d565b6000620016956200168e62001ed7565b8862002549565b905060008180620016ac5750620016ac88620025f8565b90506000620016bb896200267e565b905060005b8481101562001a01576000888281518110620016e057620016e06200353b565b60200260200101519050620016f58162000fa8565b15620017025750620019ec565b6000808984815181106200171a576200171a6200353b565b602002602001015160405160200162001734919062003272565b6040516020818303038152906040528051906020012090507f5763814b98a3aa86f212797af3273868b5dd6e2a532d764a79b98ca859e7bbad8114156200179457856200178457505050620019ec565b633cd6ee6d60e01b9150620018d7565b7fec78d9c22c08bb9f0ecd5d95571ae83e3f22219c5a9278c3270691d50abfd91b811415620017e95784158015620017ca575085155b15620017d957505050620019ec565b6360c6ff4360e01b9150620018d7565b7fda199c0e76f665e0450020791c7f8eacc75f3cdbace313272c28f93e5390b62c8114156200183e57841580156200181f575085155b156200182e57505050620019ec565b63037699c160e01b9150620018d7565b7f1d4a390f291e2e1f29874769efdef47ddad94d76f77ff516fad206a385e8995f8114156200188657866200187657505050620019ec565b63d1cf834f60e01b9150620018d7565b7fb460dcb6fd5797fc0e7ea0f13406c80d30702ba7f73a42bd91394775dcbca718811415620018ce5786620018be57505050620019ec565b63d289d1cb60e01b9150620018d7565b505050620019ec565b620018e4836001620026f9565b6000306001600160a01b0316838b87815181106200190657620019066200353b565b602002602001015160405160240162001920919062002f9c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905162001960919062003272565b6000604051808303816000865af19150503d80600081146200199f576040519150601f19603f3d011682016040523d82523d6000602084013e620019a4565b606091505b50509050620019b48482620026f9565b8015620019e75760405184907fa74c8847d513feba22a0f0cb38d53081abf97562cdb293926ba243689e7c41ca90600090a25b505050505b80620019f88162003290565b915050620016c0565b50505050505050505050505050565b7fd51dc9b187568bb94760866e1d0d066ca470037d2d331afb1a02ec74bfb8990c60009081526020527ff8d0c05cd32e3272241fdc9d5839565f8bcf94139cb4bd09e230e1b57a60ddc25490565b600062001a706200028784846200270c565b9392505050565b600062001a8a6200028785858562002763565b949350505050565b620004b762001aa385858562002763565b8262001b49565b600062001a70620003968484620027d7565b62001adf62001acc8484620027d7565b8260009182526020829052604090912055565b505050565b6000620008eb62000396836200281a565b60007f1a7261d3a36c4ce4235d10859911c9444a6963a3591ec5725b96871d9810626b8260405160200162001b2c92919062003825565b604051602081830303815290604052805190602001209050919050565b600091825260046020526040909120805460ff1916911515919091179055565b6000620008eb620003968362002856565b600062001a70620001d8848462002892565b600062001b9984620008f1565b6001600160a01b03161462001bdf5760405162461bcd60e51b815260206004820152600b60248201526a1513d2d15397d1561254d560aa1b60448201526064016200048d565b60008360405160200162001bf4919062003272565b6040516020818303038152906040528051906020012090506000818686868660405162001c219062002d80565b62001c3094939291906200384d565b8190604051809103906000f590508015801562001c51573d6000803e3d6000fd5b50905062001c608582620028d5565b7fbf90b5a1ec9763e8bf4b9245cef0c28db92bab309fc2c5177f17814f38246938858260405162001c939291906200388d565b60405180910390a1505050505050565b600062001cb084620008f1565b90506001600160a01b03811662001cfc5760405162461bcd60e51b815260206004820152600f60248201526e1513d2d15397d393d517d1561254d5608a1b60448201526064016200048d565b6040516340c10f1960e01b81526001600160a01b038481166004830152602482018490528216906340c10f1990604401600060405180830381600087803b15801562001d4757600080fd5b505af115801562000ee2573d6000803e3d6000fd5b60007fc4e632779a6a7838736dd7e5e6a0eadf171dd37dfb6230720e265576dfcf42bb8260405160200162001b2c92919062003825565b50565b81518181101562001dd75760405162461bcd60e51b815260206004820152600a602482015269494e565f41444d494e5360b01b60448201526064016200048d565b6000821162001e1a5760405162461bcd60e51b815260206004820152600e60248201526d12539597d05113525397d512131160921b60448201526064016200048d565b62001e268483620028eb565b62001e328482620028fa565b60005b818110156200075557600084828151811062001e555762001e556200353b565b6020026020010151905062001e6b868262001a5e565b1562001ea65760405162461bcd60e51b8152602060048201526009602482015268222aa82fa0a226a4a760b91b60448201526064016200048d565b62001eb386838362002909565b62001ec18682600162002919565b508062001ece8162003290565b91505062001e35565b7f67cbdff49954077d2dd5637524b03bfe3e6506d456859017a888fad567e1af0360009081526020527f06f01c2f096e745c2a207fbf93babd5e7ee6acfd26f0f34a0e4ac68373c21d0e5490565b7f67cbdff49954077d2dd5637524b03bfe3e6506d456859017a888fad567e1af0360009081526020527f06f01c2f096e745c2a207fbf93babd5e7ee6acfd26f0f34a0e4ac68373c21d0e55565b81518181101562001fb35760405162461bcd60e51b815260206004820152600a602482015269494e565f4f574e45525360b01b60448201526064016200048d565b6000821162001ff65760405162461bcd60e51b815260206004820152600e60248201526d12539597d3d5d3915497d512131160921b60448201526064016200048d565b62002002848362002929565b6200200e848262002938565b60005b81811015620007555760008482815181106200203157620020316200353b565b6020026020010151905062002047868262002947565b15620020825760405162461bcd60e51b8152602060048201526009602482015268222aa82fa7aba722a960b91b60448201526064016200048d565b6200208f86838362002959565b6200209d86826001620029ad565b5080620020aa8162003290565b91505062002011565b7f5369fb791f26307f8e69b07625302ccac6930af09ab22d753b17d2042e9992e760009081526020527f07174c149a4f7627ac1dd39b679bd42f12fc4e8d7e850b055662bbee7188da105490565b7f5369fb791f26307f8e69b07625302ccac6930af09ab22d753b17d2042e9992e760009081526020527f07174c149a4f7627ac1dd39b679bd42f12fc4e8d7e850b055662bbee7188da1055565b815181811015620021925760405162461bcd60e51b815260206004820152600d60248201526c494e565f4f50455241544f525360981b60448201526064016200048d565b60008211620021d85760405162461bcd60e51b815260206004820152601160248201527012539597d3d41154905513d497d5121311607a1b60448201526064016200048d565b620021e48483620029bd565b620021f08482620029cc565b60005b81811015620007555760008482815181106200221357620022136200353b565b60200260200101519050620022298682620029db565b15620022675760405162461bcd60e51b815260206004820152600c60248201526b222aa82fa7a822a920aa27a960a11b60448201526064016200048d565b62002274868383620029ed565b6200228286826001620029fd565b50806200228f8162003290565b915050620021f3565b6000620008eb620003968362002a0d565b600062001a70620001d8848462002a49565b62001d937f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8262002a8c565b6000620008eb620003968362002aba565b604080517f957705a374326b30f4a1069c936d736cc9993ed6c820b4e0e2fd94a8beca0d1d602082015290810182905260009060600162001b2c565b6000620008eb620003968362002af6565b6000620008eb620003968362002b32565b600062001a70620001d8848462002b6e565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c0162001b2c565b60008151604114620023e35760405162461bcd60e51b815260206004820152600760248201526624a72b2fa622a760c91b60448201526064016200048d565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156200244f5760405162461bcd60e51b8152602060048201526005602482015264494e565f5360d81b60448201526064016200048d565b8060ff16601b14806200246557508060ff16601c145b6200249b5760405162461bcd60e51b815260206004820152600560248201526424a72b2fab60d91b60448201526064016200048d565b6040805160008082526020820180845289905260ff841692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015620024f0573d6000803e3d6000fd5b505050602060405103519450846001600160a01b03161415620025405760405162461bcd60e51b8152602060048201526007602482015266494e565f53494760c81b60448201526064016200048d565b50505092915050565b6000620025568262002bb1565b156200256557506000620008eb565b60006200257284620022e7565b90506000805b8451811015620025ec57620025aa868683815181106200259c576200259c6200353b565b602002602001015162002947565b8015620025c4575082620025be8362003290565b92508210155b15620025d75760019350505050620008eb565b80620025e38162003290565b91505062002578565b50600095945050505050565b6000806200260562001ed7565b90506000620026176001601062003257565b905060008183116200262b57600062002637565b620026378284620038b9565b90505b8083111562002673576200265c836200265381620038d3565b94508662002549565b156200266d57506001949350505050565b6200263a565b506000949350505050565b6000806200268b620020b3565b905060006200269d6001601062003257565b90506000818311620026b1576000620026bd565b620026bd8284620038b9565b90505b808311156200267357620026e283620026d981620038d3565b94508662002c6b565b15620026f357506001949350505050565b620026c0565b6200270862001aa383620022f8565b5050565b60007f63fa879cb478fddf1de08d49e29115fb768866711bc799ff9ab419a7f16c9afb83836040516020016200274593929190620038ed565b60405160208183030381529060405280519060200120905092915050565b604080517f3ced7a8caf1111e0fbf4b784c5b41aebd0f2389d9f2f64d5c3424aeed3adbd3c6020820152908101849052606080820184905282901b6bffffffffffffffffffffffff191660808201526000906094016040516020818303038152906040528051906020012090509392505050565b604080517fbaea1c6c0f16a0a340b10a9e980806696a68ddbb5e8361fd64630dd21abf515f60208201529081018390526060810182905260009060800162002745565b604080517f79bd914addd90bd67ad800bf0230bb85ffdef5aeba5fd8249f116d3f17f4fb4b602082015290810182905260009060600162001b2c565b604080517f05112ef894367de1270cfae12afcd2285c225830eb8f74e7e938f721bb510cba602082015290810182905260009060600162001b2c565b604080517ff23ec0bb4210edd5cba85afd05127efcd2fc6a781bfed49188da1081670b22d860208201529081018390526060810182905260009060800162002745565b62002708620028e48362001d5c565b8262002a8c565b6200270862001acc836200281a565b6200270862001acc8362002856565b62001adf620028e4848462002892565b62001adf62001aa384846200270c565b6200270862001acc8362002aba565b6200270862001acc8362002a0d565b600062001a7062000287848462002d0e565b6001600160a01b0381166200299d5760405162461bcd60e51b81526020600482015260096024820152682d22a927afa0a2222960b91b60448201526064016200048d565b62001adf620028e4848462002a49565b62001adf62001aa3848462002d0e565b6200270862001acc8362002af6565b6200270862001acc8362002b32565b600062001a7062000287848462002d47565b62001adf620028e4848462002b6e565b62001adf62001aa3848462002d47565b604080517f4ededbb904acd1258c7b9a6b12f5a8a8870a8ec295809cf35dc1f098018d4d20602082015290810182905260009060600162001b2c565b604080517f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060208201529081018390526060810182905260009060800162002745565b60009182526002602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b604080517f2bd864201f87ce8cc2d875453b39cc3e981d8ee12e4b7d4b7492fd9404bd8229602082015290810182905260009060600162001b2c565b604080517fc0e594a04ce768761133f7238cd95a55441f8ee2d50a03e7d5c44fb26c04d76f602082015290810182905260009060600162001b2c565b604080517f6199febc552b750a8cf661862e77cb2dbed9f3fb6fcc10bd34f8ff9e1992362b602082015290810182905260009060600162001b2c565b604080517f46a52cf33029de9f84853745a87af28464c80bf0346df1b32e205fc73319f62260208201529081018390526060810182905260009060800162002745565b8051600090815b8181101562002c6157600062002bd082600162003257565b90505b8281101562002c4d5784818151811062002bf15762002bf16200353b565b60200260200101516001600160a01b031685838151811062002c175762002c176200353b565b60200260200101516001600160a01b0316141562002c3a57506001949350505050565b62002c458162003290565b905062002bd3565b5062002c598162003290565b905062002bb8565b5060009392505050565b600062002c788262002bb1565b1562002c8757506000620008eb565b600062002c948462002334565b90506000805b8451811015620025ec5762002ccc8686838151811062002cbe5762002cbe6200353b565b6020026020010151620029db565b801562002ce657508262002ce08362003290565b92508210155b1562002cf95760019350505050620008eb565b8062002d058162003290565b91505062002c9a565b60007fffbbd206dad2a77ed223a0ff3d2dcac502bc8c9a91fa18140757561e84f365c083836040516020016200274593929190620038ed565b60007f934404a25b467ba4b73107cf91baadb1313f82988678493324b442216995358683836040516020016200274593929190620038ed565b6112eb806200391683390190565b60008083601f84011262002da157600080fd5b5081356001600160401b0381111562002db957600080fd5b60208301915083602082850101111562002dd257600080fd5b9250929050565b6000806020838503121562002ded57600080fd5b82356001600160401b0381111562002e0457600080fd5b62002e128582860162002d8e565b90969095509350505050565b60006020828403121562002e3157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562002e795762002e7962002e38565b604052919050565b60006001600160401b0382111562002e9d5762002e9d62002e38565b50601f01601f191660200190565b600082601f83011262002ebd57600080fd5b813562002ed462002ece8262002e81565b62002e4e565b81815284602083860101111562002eea57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121562002f1a57600080fd5b81356001600160401b0381111562002f3157600080fd5b62001a8a8482850162002eab565b60005b8381101562002f5c57818101518382015260200162002f42565b83811115620004b75750506000910152565b6000815180845262002f8881602086016020860162002f3f565b601f01601f19169290920160200192915050565b60208152600062001a70602083018462002f6e565b600081518084526020808501945080840160005b8381101562002fec5781516001600160a01b03168752958201959082019060010162002fc5565b509495945050505050565b60208152600062001a70602083018462002fb1565b6001600160a01b038116811462001d9357600080fd5b6000806000604084860312156200303857600080fd5b833562003045816200300c565b925060208401356001600160401b038111156200306157600080fd5b6200306f8682870162002d8e565b9497909650939450505050565b6020808252600890820152672727aa2fa9a2a62360c11b604082015260600190565b60008060408385031215620030b257600080fd5b82356001600160401b03811115620030c957600080fd5b620030d78582860162002eab565b95602094909401359450505050565b60006001600160401b0382111562003102576200310262002e38565b5060051b60200190565b600080604083850312156200312057600080fd5b82356001600160401b03808211156200313857600080fd5b620031468683870162002eab565b93506020915081850135818111156200315e57600080fd5b8501601f810187136200317057600080fd5b80356200318162002ece82620030e6565b81815260059190911b82018401908481019089831115620031a157600080fd5b8584015b83811015620031de57803586811115620031bf5760008081fd5b620031cf8c898389010162002eab565b845250918601918601620031a5565b508096505050505050509250929050565b6020808252600990820152682727aa2fa0a226a4a760b91b604082015260600190565b8183823760009101908152919050565b6020808252600590820152641593d5115160da1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b600082198211156200326d576200326d62003241565b500190565b600082516200328681846020870162002f3f565b9190910192915050565b6000600019821415620032a757620032a762003241565b5060010190565b60008060008060808587031215620032c557600080fd5b84356001600160401b0380821115620032dd57600080fd5b620032eb8883890162002eab565b955060208701359150808211156200330257600080fd5b50620033118782880162002eab565b935050604085013560ff811681146200332957600080fd5b9396929550929360600135925050565b6000806000606084860312156200334f57600080fd5b83356001600160401b038111156200336657600080fd5b620033748682870162002eab565b935050602084013562003387816200300c565b929592945050506040919091013590565b600181811c90821680620033ad57607f821691505b60208210811415620033cf57634e487b7160e01b600052602260045260246000fd5b50919050565b600082601f830112620033e757600080fd5b81356020620033fa62002ece83620030e6565b82815260059290921b840181019181810190868411156200341a57600080fd5b8286015b848110156200344257803562003434816200300c565b83529183019183016200341e565b509695505050505050565b60008060008060008060c087890312156200346757600080fd5b86356001600160401b03808211156200347f57600080fd5b6200348d8a838b01620033d5565b9750602089013596506040890135915080821115620034ab57600080fd5b620034b98a838b01620033d5565b9550606089013594506080890135915080821115620034d757600080fd5b50620034e689828a01620033d5565b92505060a087013590509295509295509295565b6080815260006200350f608083018762002fb1565b856020840152828103604084015262003529818662002fb1565b91505082606083015295945050505050565b634e487b7160e01b600052603260045260246000fd5b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600080604083850312156200359457600080fd5b82356001600160401b03811115620035ab57600080fd5b620030d785828601620033d5565b6000620035ca62002ece8462002e81565b9050828152838383011115620035df57600080fd5b62001a7083602083018462002f3f565b600082601f8301126200360157600080fd5b815160206200361462002ece83620030e6565b82815260059290921b840181019181810190868411156200363457600080fd5b8286015b84811015620034425780516001600160401b03811115620036595760008081fd5b8701603f810189136200366c5760008081fd5b6200367f898683015160408401620035b9565b84525091830191830162003638565b600082601f830112620036a057600080fd5b81516020620036b362002ece83620030e6565b82815260059290921b84018101918181019086841115620036d357600080fd5b8286015b84811015620034425780516001600160401b03811115620036f85760008081fd5b8701603f810189136200370b5760008081fd5b6200371e898683015160408401620035b9565b845250918301918301620036d7565b600080600080608085870312156200374457600080fd5b845193506020808601516001600160401b03808211156200376457600080fd5b818801915088601f8301126200377957600080fd5b81516200378a62002ece82620030e6565b81815260059190911b8301840190848101908b831115620037aa57600080fd5b938501935b82851015620037ca57845182529385019390850190620037af565b60408b01519098509450505080831115620037e457600080fd5b620037f289848a01620035ef565b945060608801519250808311156200380957600080fd5b505062003819878288016200368e565b91505092959194509250565b828152600082516200383f81602085016020870162002f3f565b919091016020019392505050565b60808152600062003862608083018762002f6e565b828103602084015262003876818762002f6e565b60ff95909516604084015250506060015292915050565b604081526000620038a2604083018562002f6e565b905060018060a01b03831660208301529392505050565b600082821015620038ce57620038ce62003241565b500390565b600081620038e557620038e562003241565b506000190190565b928352602083019190915260601b6bffffffffffffffffffffffff191660408201526054019056fe60a06040523480156200001157600080fd5b50604051620012eb380380620012eb83398101604081905262000034916200022e565b83838382600390805190602001906200004f929190620000bb565b50815162000065906004906020850190620000bb565b5060ff166080525050600580546001600160a01b031916339081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a360065550620002f6915050565b828054620000c990620002b9565b90600052602060002090601f016020900481019282620000ed576000855562000138565b82601f106200010857805160ff191683800117855562000138565b8280016001018555821562000138579182015b82811115620001385782518255916020019190600101906200011b565b50620001469291506200014a565b5090565b5b808211156200014657600081556001016200014b565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200018957600080fd5b81516001600160401b0380821115620001a657620001a662000161565b604051601f8301601f19908116603f01168101908282118183101715620001d157620001d162000161565b81604052838152602092508683858801011115620001ee57600080fd5b600091505b83821015620002125785820183015181830184015290820190620001f3565b83821115620002245760008385830101525b9695505050505050565b600080600080608085870312156200024557600080fd5b84516001600160401b03808211156200025d57600080fd5b6200026b8883890162000177565b955060208701519150808211156200028257600080fd5b50620002918782880162000177565b935050604085015160ff81168114620002a957600080fd5b6060959095015193969295505050565b600181811c90821680620002ce57607f821691505b60208210811415620002f057634e487b7160e01b600052602260045260246000fd5b50919050565b608051610fd96200031260003960006101950152610fd96000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806339509351116100a257806395d89b411161007157806395d89b4114610256578063a457c2d71461025e578063a9059cbb14610271578063dd62ed3e14610284578063f2fde38b146102af57600080fd5b806339509351146101fd57806340c10f191461021057806370a08231146102235780638da5cb5b1461024357600080fd5b806323b872dd116100de57806323b872dd1461017d578063313ce5671461019057806331eecaf4146101c9578063355274ea146101f457600080fd5b806306fdde031461011057806308a1eee11461012e578063095ea7b31461014357806318160ddd14610166575b600080fd5b6101186102c2565b6040516101259190610bf8565b60405180910390f35b61014161013c366004610c2b565b610350565b005b610156610151366004610c60565b6103b9565b6040519015158152602001610125565b61016f60025481565b604051908152602001610125565b61015661018b366004610c8a565b6103cf565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610125565b6101dc6101d7366004610c2b565b610421565b6040516001600160a01b039091168152602001610125565b61016f60065481565b61015661020b366004610c60565b610505565b61014161021e366004610c60565b61053c565b61016f610231366004610cc6565b60006020819052908152604090205481565b6005546101dc906001600160a01b031681565b6101186105cd565b61015661026c366004610c60565b6105da565b61015661027f366004610c60565b610611565b61016f610292366004610ce8565b600160209081526000928352604080842090915290825290205481565b6101416102bd366004610cc6565b61061e565b600380546102cf90610d1b565b80601f01602080910402602001604051908101604052809291908181526020018280546102fb90610d1b565b80156103485780601f1061031d57610100808354040283529160200191610348565b820191906000526020600020905b81548152906001019060200180831161032b57829003601f168201915b505050505081565b6005546001600160a01b031633146103835760405162461bcd60e51b815260040161037a90610d56565b60405180910390fd5b600061038e82610421565b6001600160a01b0381166000908152602081905260409020549091506103b59082906106ca565b5050565b60006103c6338484610788565b50600192915050565b60006103dc848484610836565b6001600160a01b038416600090815260016020908152604080832033808552925290912054610417918691610412908690610d8f565b610788565b5060019392505050565b6005546040516000916001600160f81b0319916001600160a01b0390911690849061044e60208201610bbc565b601f1982820381018352601f9091011660408181523060208301520160408051601f198184030181529082905261048a92918890602001610da6565b604051602081830303815290604052805190602001206040516020016104e794939291906001600160f81b031994909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051601f19818403018152919052805160209091012092915050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916103c6918590610412908690610ddb565b6005546001600160a01b031633146105665760405162461bcd60e51b815260040161037a90610d56565b600654801580610583575080826002546105809190610ddb565b11155b6105be5760405162461bcd60e51b815260206004820152600c60248201526b10d05417d15610d15151115160a21b604482015260640161037a565b6105c8838361092e565b505050565b600480546102cf90610d1b565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916103c6918590610412908690610d8f565b60006103c6338484610836565b6005546001600160a01b031633146106485760405162461bcd60e51b815260040161037a90610d56565b6001600160a01b03811661066e5760405162461bcd60e51b815260040161037a90610df3565b6005546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382166106f05760405162461bcd60e51b815260040161037a90610df3565b6106fc826000836109e2565b6001600160a01b03821660009081526020819052604081208054839290610724908490610d8f565b92505081905550806002600082825461073d9190610d8f565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6001600160a01b0383166107ae5760405162461bcd60e51b815260040161037a90610df3565b6001600160a01b0382166107d45760405162461bcd60e51b815260040161037a90610df3565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03831661085c5760405162461bcd60e51b815260040161037a90610df3565b6001600160a01b0382166108825760405162461bcd60e51b815260040161037a90610df3565b61088d8383836109e2565b6001600160a01b038316600090815260208190526040812080548392906108b5908490610d8f565b90915550506001600160a01b038216600090815260208190526040812080548392906108e2908490610ddb565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161082991815260200190565b6001600160a01b0382166109545760405162461bcd60e51b815260040161037a90610df3565b610960600083836109e2565b80600260008282546109729190610ddb565b90915550506001600160a01b0382166000908152602081905260408120805483929061099f908490610ddb565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161077c565b600554604051633d70e7e560e11b81527f75a31d1ce8e5f9892188befc328d3b9bd3fa5037457e881abc21f388471b8d9660048201526001600160a01b0390911690637ae1cfca9060240160206040518083038186803b158015610a4557600080fd5b505afa158015610a59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7d9190610e16565b15610ab65760405162461bcd60e51b815260206004820152600960248201526824a9afa32927ad22a760b91b604482015260640161037a565b6005546040516001600160a01b0390911690637ae1cfca90610aff907f1a7261d3a36c4ce4235d10859911c9444a6963a3591ec5725b96871d9810626b90600490602001610e38565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610b3391815260200190565b60206040518083038186803b158015610b4b57600080fd5b505afa158015610b5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b839190610e16565b156105c85760405162461bcd60e51b815260206004820152600960248201526824a9afa32927ad22a760b91b604482015260640161037a565b60c280610ee283390190565b60005b83811015610be3578181015183820152602001610bcb565b83811115610bf2576000848401525b50505050565b6020815260008251806020840152610c17816040850160208701610bc8565b601f01601f19169190910160400192915050565b600060208284031215610c3d57600080fd5b5035919050565b80356001600160a01b0381168114610c5b57600080fd5b919050565b60008060408385031215610c7357600080fd5b610c7c83610c44565b946020939093013593505050565b600080600060608486031215610c9f57600080fd5b610ca884610c44565b9250610cb660208501610c44565b9150604084013590509250925092565b600060208284031215610cd857600080fd5b610ce182610c44565b9392505050565b60008060408385031215610cfb57600080fd5b610d0483610c44565b9150610d1260208401610c44565b90509250929050565b600181811c90821680610d2f57607f821691505b60208210811415610d5057634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600990820152682727aa2fa7aba722a960b91b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b600082821015610da157610da1610d79565b500390565b60008451610db8818460208901610bc8565b845190830190610dcc818360208901610bc8565b01928352505060200192915050565b60008219821115610dee57610dee610d79565b500190565b6020808252600990820152682d22a927afa0a2222960b91b604082015260600190565b600060208284031215610e2857600080fd5b81518015158114610ce157600080fd5b828152600060206000845481600182811c915080831680610e5a57607f831692505b858310811415610e7857634e487b7160e01b85526022600452602485fd5b808015610e8c5760018114610ea157610ed2565b60ff1985168988015283890187019550610ed2565b60008a81526020902060005b85811015610ec85781548b82018a0152908401908801610ead565b505086848a010195505b5093999850505050505050505056fe6080604052348015600f57600080fd5b506040516100c23803806100c2833981016040819052602c916089565b6040516308a1eee160e01b8152600481018290526001600160a01b038316906308a1eee190602401600060405180830381600087803b158015606d57600080fd5b505af11580156080573d6000803e3d6000fd5b50600092505050ff5b60008060408385031215609b57600080fd5b82516001600160a01b038116811460b157600080fd5b602093909301519294929350505056fea26469706673582212200b9d4704dcf13dfd9787296fefb091302153358bea4f3d74f0ba4e11a9cb95aa64736f6c63430008090033a2646970667358221220650a3d16decebe4547c4596d6c58eb39fc086a5e2785d73373e140c33d3203ab64736f6c634300080900330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000015837c1318ab83d99b19392fd4811813f520d84300000000000000000000000064247a441cef0b7a46614ac34d046c0fdfe35954000000000000000000000000ee64c8eb48437dbd2d5b8598dc4a3e8a6c8cead9000000000000000000000000b69f9beeec3e245ea4631b74c222b04e155a5c26000000000000000000000000eb73eca75e40cf21dcfd64de640d678b60082d580000000000000000000000006d0a01a933ee446e58aec5e55d632e4251244fcc0000000000000000000000005ca6b6a137040c59f3da13c960fb6cf9e2b9f6380000000000000000000000002a923c9428233470e25f0fd1cef5c8831d4407f300000000000000000000000000000000000000000000000000000000000000050000000000000000000000004ab2ecd8a3c6e9e15ce86443ae6d651767e1a69e0000000000000000000000007b4e160fc608d3cc1d19e79af060a4b5d8944dd00000000000000000000000007d94343761f46f4d6c9198fb3457051c54cfa7a70000000000000000000000007f510e3aeb75e545ff70c505aefdde4b4e4b33ce000000000000000000000000655449bc1bd52de2fb6cc574dd655864d927fe300000000000000000000000000000000000000000000000000000000000000006000000000000000000000000fccba2c14a58732cf5fd680c44b0f4d20d60b9fa0000000000000000000000006c8282c50a95aab8b6704f8158bcf618547a6ac30000000000000000000000005b31da5499476e5c49f9ba250b7267b3aafd8a3b000000000000000000000000f7551663ba876da1c528f1c0634e6c48474864bb0000000000000000000000000e0c6c50f617752f6212684bda8900a7df529f230000000000000000000000005f2937ecaaa81b99f7866cbdfbb5434b369c3301

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000015837c1318ab83d99b19392fd4811813f520d84300000000000000000000000064247a441cef0b7a46614ac34d046c0fdfe35954000000000000000000000000ee64c8eb48437dbd2d5b8598dc4a3e8a6c8cead9000000000000000000000000b69f9beeec3e245ea4631b74c222b04e155a5c26000000000000000000000000eb73eca75e40cf21dcfd64de640d678b60082d580000000000000000000000006d0a01a933ee446e58aec5e55d632e4251244fcc0000000000000000000000005ca6b6a137040c59f3da13c960fb6cf9e2b9f6380000000000000000000000002a923c9428233470e25f0fd1cef5c8831d4407f300000000000000000000000000000000000000000000000000000000000000050000000000000000000000004ab2ecd8a3c6e9e15ce86443ae6d651767e1a69e0000000000000000000000007b4e160fc608d3cc1d19e79af060a4b5d8944dd00000000000000000000000007d94343761f46f4d6c9198fb3457051c54cfa7a70000000000000000000000007f510e3aeb75e545ff70c505aefdde4b4e4b33ce000000000000000000000000655449bc1bd52de2fb6cc574dd655864d927fe300000000000000000000000000000000000000000000000000000000000000006000000000000000000000000fccba2c14a58732cf5fd680c44b0f4d20d60b9fa0000000000000000000000006c8282c50a95aab8b6704f8158bcf618547a6ac30000000000000000000000005b31da5499476e5c49f9ba250b7267b3aafd8a3b000000000000000000000000f7551663ba876da1c528f1c0634e6c48474864bb0000000000000000000000000e0c6c50f617752f6212684bda8900a7df529f230000000000000000000000005f2937ecaaa81b99f7866cbdfbb5434b369c3301

-----Decoded View---------------
Arg [0] : params (bytes): 0x00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000015837c1318ab83d99b19392fd4811813f520d84300000000000000000000000064247a441cef0b7a46614ac34d046c0fdfe35954000000000000000000000000ee64c8eb48437dbd2d5b8598dc4a3e8a6c8cead9000000000000000000000000b69f9beeec3e245ea4631b74c222b04e155a5c26000000000000000000000000eb73eca75e40cf21dcfd64de640d678b60082d580000000000000000000000006d0a01a933ee446e58aec5e55d632e4251244fcc0000000000000000000000005ca6b6a137040c59f3da13c960fb6cf9e2b9f6380000000000000000000000002a923c9428233470e25f0fd1cef5c8831d4407f300000000000000000000000000000000000000000000000000000000000000050000000000000000000000004ab2ecd8a3c6e9e15ce86443ae6d651767e1a69e0000000000000000000000007b4e160fc608d3cc1d19e79af060a4b5d8944dd00000000000000000000000007d94343761f46f4d6c9198fb3457051c54cfa7a70000000000000000000000007f510e3aeb75e545ff70c505aefdde4b4e4b33ce000000000000000000000000655449bc1bd52de2fb6cc574dd655864d927fe300000000000000000000000000000000000000000000000000000000000000006000000000000000000000000fccba2c14a58732cf5fd680c44b0f4d20d60b9fa0000000000000000000000006c8282c50a95aab8b6704f8158bcf618547a6ac30000000000000000000000005b31da5499476e5c49f9ba250b7267b3aafd8a3b000000000000000000000000f7551663ba876da1c528f1c0634e6c48474864bb0000000000000000000000000e0c6c50f617752f6212684bda8900a7df529f230000000000000000000000005f2937ecaaa81b99f7866cbdfbb5434b369c3301

-----Encoded View---------------
30 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000380
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [6] : 00000000000000000000000000000000000000000000000000000000000002a0
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [9] : 00000000000000000000000015837c1318ab83d99b19392fd4811813f520d843
Arg [10] : 00000000000000000000000064247a441cef0b7a46614ac34d046c0fdfe35954
Arg [11] : 000000000000000000000000ee64c8eb48437dbd2d5b8598dc4a3e8a6c8cead9
Arg [12] : 000000000000000000000000b69f9beeec3e245ea4631b74c222b04e155a5c26
Arg [13] : 000000000000000000000000eb73eca75e40cf21dcfd64de640d678b60082d58
Arg [14] : 0000000000000000000000006d0a01a933ee446e58aec5e55d632e4251244fcc
Arg [15] : 0000000000000000000000005ca6b6a137040c59f3da13c960fb6cf9e2b9f638
Arg [16] : 0000000000000000000000002a923c9428233470e25f0fd1cef5c8831d4407f3
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [18] : 0000000000000000000000004ab2ecd8a3c6e9e15ce86443ae6d651767e1a69e
Arg [19] : 0000000000000000000000007b4e160fc608d3cc1d19e79af060a4b5d8944dd0
Arg [20] : 0000000000000000000000007d94343761f46f4d6c9198fb3457051c54cfa7a7
Arg [21] : 0000000000000000000000007f510e3aeb75e545ff70c505aefdde4b4e4b33ce
Arg [22] : 000000000000000000000000655449bc1bd52de2fb6cc574dd655864d927fe30
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [24] : 000000000000000000000000fccba2c14a58732cf5fd680c44b0f4d20d60b9fa
Arg [25] : 0000000000000000000000006c8282c50a95aab8b6704f8158bcf618547a6ac3
Arg [26] : 0000000000000000000000005b31da5499476e5c49f9ba250b7267b3aafd8a3b
Arg [27] : 000000000000000000000000f7551663ba876da1c528f1c0634e6c48474864bb
Arg [28] : 0000000000000000000000000e0c6c50f617752f6212684bda8900a7df529f23
Arg [29] : 0000000000000000000000005f2937ecaaa81b99f7866cbdfbb5434b369c3301


Deployed ByteCode Sourcemap

55505:575:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5822:18;;-1:-1:-1;;;5822:18:0;;216:2:1;5822:18:0;;;198:21:1;255:1;235:18;;;228:29;-1:-1:-1;;;273:18:1;;;266:38;321:18;;5822::0;;;;;;;55505:575;5179:66;5294:22;916:20;;;:15;:20;;;;-1:-1:-1;;;;;916:20:0;;5405:14;;5294:22;5386:34;5508:1;5505;5489:14;5486:1;5470:14;5463:5;5450:60;5547:16;5544:1;5541;5526:38;5587:6;5607:68;;;;5726:16;5723:1;5716:27;5607:68;5643:16;5640:1;5633:27;835:109;;;;;;;;;;-1:-1:-1;835:109:0;;;;;:::i;:::-;889:7;916:20;;;:15;:20;;;;;;-1:-1:-1;;;;;916:20:0;;835:109;;;;-1:-1:-1;;;;;699:32:1;;;681:51;;669:2;654:18;835:109:0;;;;;;;;1070:100;;;;;;;;;;-1:-1:-1;1070:100:0;;;;;:::i;:::-;1121:4;1145:17;;;:12;:17;;;;;;;;;1070:100;;;;908:14:1;;901:22;883:41;;871:2;856:18;1070:100:0;743:187:1;714:113:0;;;;;;;;;;-1:-1:-1;714:113:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;56028:49::-;;;;;;;;;;-1:-1:-1;56028:49:0;;;;;:::i;:::-;;;;;;603:103;;;;;;;;;;-1:-1:-1;603:103:0;;;;;:::i;:::-;654:7;681:17;;;;;;;;;;;;603:103;;;;2379:25:1;;;2367:2;2352:18;603:103:0;2233:177:1;952:110:0;;;;;;;;;;-1:-1:-1;952:110:0;;;;;:::i;:::-;;:::i;1178:100::-;;;;;;;;;;-1:-1:-1;1178:100:0;;;;;:::i;:::-;1228:6;1254:16;;;:11;:16;;;;;;;1178:100;714:113;800:19;;;;:14;:19;;;;;793:26;;767:13;;800:19;793:26;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;714:113;;;:::o;952:110::-;1036:18;;;;:13;:18;;;;;1029:25;;1004:12;;1036:18;1029:25;;;:::i;350:180:1:-;409:6;462:2;450:9;441:7;437:23;433:32;430:52;;;478:1;475;468:12;430:52;-1:-1:-1;501:23:1;;350:180;-1:-1:-1;350:180:1:o;935:472::-;977:3;1015:5;1009:12;1042:6;1037:3;1030:19;1067:1;1077:162;1091:6;1088:1;1085:13;1077:162;;;1153:4;1209:13;;;1205:22;;1199:29;1181:11;;;1177:20;;1170:59;1106:12;1077:162;;;1257:6;1254:1;1251:13;1248:87;;;1323:1;1316:4;1307:6;1302:3;1298:16;1294:27;1287:38;1248:87;-1:-1:-1;1389:2:1;1368:15;-1:-1:-1;;1364:29:1;1355:39;;;;1396:4;1351:50;;935:472;-1:-1:-1;;935:472:1:o;1412:220::-;1561:2;1550:9;1543:21;1524:4;1581:45;1622:2;1611:9;1607:18;1599:6;1581:45;:::i;:::-;1573:53;1412:220;-1:-1:-1;;;1412:220:1:o;1637:591::-;1707:6;1715;1768:2;1756:9;1747:7;1743:23;1739:32;1736:52;;;1784:1;1781;1774:12;1736:52;1824:9;1811:23;1853:18;1894:2;1886:6;1883:14;1880:34;;;1910:1;1907;1900:12;1880:34;1948:6;1937:9;1933:22;1923:32;;1993:7;1986:4;1982:2;1978:13;1974:27;1964:55;;2015:1;2012;2005:12;1964:55;2055:2;2042:16;2081:2;2073:6;2070:14;2067:34;;;2097:1;2094;2087:12;2067:34;2142:7;2137:2;2128:6;2124:2;2120:15;2116:24;2113:37;2110:57;;;2163:1;2160;2153:12;2110:57;2194:2;2186:11;;;;;2216:6;;-1:-1:-1;1637:591:1;;-1:-1:-1;;;;1637:591:1:o;2818:380::-;2897:1;2893:12;;;;2940;;;2961:61;;3015:4;3007:6;3003:17;2993:27;;2961:61;3068:2;3060:6;3057:14;3037:18;3034:38;3031:161;;;3114:10;3109:3;3105:20;3102:1;3095:31;3149:4;3146:1;3139:15;3177:4;3174:1;3167:15;3031:161;;2818:380;;;:::o

Swarm Source

ipfs://650a3d16decebe4547c4596d6c58eb39fc086a5e2785d73373e140c33d3203ab
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading