Contract 0x25ab3efd52e6470681ce037cd546dc60726948d3 28

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x7ce334e6e3ea90c1e12e09f3e2eace136168e5f7dcf78e6d73c4a4242e6b4a120xc8173c441954632092024-03-29 14:29:1220 secs ago0x950360eb0ed60487e8284db77d0a72edec24e7e8 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30.1139 ETH0.000002450.01
0x5db168010bbc5768c192ccc45fdd1df2f15a624e4f45ee6863fd1b25038a4ac10xc8173c441954631382024-03-29 14:28:5438 secs ago0x8bd2d1f7d68db43e54c187a78e65a543949b9f1c IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000283 0.01
0x265a486059af9ac684be342ca54caf00cecd2102bb4dcd4f05fb91dd2862bab60xab115fd81954630962024-03-29 14:28:4448 secs ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000281 0.01
0x1e61033209df0abb44ad06885bb393c298c1ed64b31d8a4cb646d3491020165f0x58d9b4e11954630862024-03-29 14:28:4151 secs ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000181 0.01
0x7117da3580328038412894c7bdc69fd2768a4922df38996243a30cf5638cdc370xc8173c441954630592024-03-29 14:28:3557 secs ago0x6b73cca178de308eb24e2cf5d964699de4351edf IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.000002770.01
0xc7612a57a61fbd8c1b64ca98f5934f4c48e5e8896fcb8652435ca18f591dc6110x827c87cc1954630532024-03-29 14:28:3359 secs ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000229 0.01
0xfa5fc885afe49f8e1d86d56680ccd1508b79b696c426e214d67c2cf0085372fd0xab115fd81954630502024-03-29 14:28:321 min ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000298 0.01
0x7871be0b926987951953c5440a80da2057d56cfaac798468a99784086b2309200x827c87cc1954630462024-03-29 14:28:311 min ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000229 0.01
0x12d74574134a82fb9b8b873e4a35e226772bd1aafb42d17b56b8169a1064a8eb0x827c87cc1954630282024-03-29 14:28:271 min ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000229 0.01
0xd17b8ea67b4930d10da06a6fd80bea28e746d345d98a1af054aaadfecd17c0d80x58d9b4e11954625522024-03-29 14:26:263 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000181 0.01
0xeffdea7ddbe3634b9aef8126792d891ee9e0c0592ba00435dff07ccda91a81e70xab115fd81954625442024-03-29 14:26:233 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000294 0.01
0x2582b660b9a0a1d0b86044155b9027075e7859279902f7ced974609aa5ce54a60xab115fd81954625382024-03-29 14:26:213 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000259 0.01
0xa3f5e3e20707368c830ff0e18f33a246d6cb59a660bc89dd0419ea3d7d2ea3480xc8173c441954624442024-03-29 14:25:573 mins ago0x9c50d01c356a172d754c5a583435a552401970d5 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000272 0.01
0x32def5c7fc8de4f0ae12122453193ed710951e73999fd1031057b0a7e77c458d0xc8173c441954623752024-03-29 14:25:413 mins ago0x8bd2d1f7d68db43e54c187a78e65a543949b9f1c IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000258 0.01
0x61cd67613b39e52d001a908fcc4a4baec920b32e226b07e18b34a2a321a08c020xdecf2a481954621942024-03-29 14:24:554 mins ago0xb3d29057fbf7cc83f498898fc516bfbdc71a4249 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.000001820.01
0xbb6165fa1aa68e5bf1fec919dd38cde41eb7b2f3d38521c0140eab323e6fa7630x827c87cc1954621372024-03-29 14:24:404 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000204 0.01
0x4308387499f66e42d443b3e3e059375f0a3fead3560054249a6ef05a7ff91d510xab115fd81954619812024-03-29 14:24:005 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000272 0.01
0x9315f6deb1aba4fe8008ad1d8b268b270ec5cb86a80ffed343bbbdba81d8442e0xdecf2a481954619312024-03-29 14:23:475 mins ago0x5d8043a699ca3992febc6f409474f28481608564 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.000001810.01
0x09cdc0aaa48a5c6d8aeeecf9f06a5cf308769ec7370ce089542708dda74949cf0x827c87cc1954619192024-03-29 14:23:445 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000203 0.01
0xaf775cc079908d1a617e8d6a825887bbe9da81629dcb1c4f7bde1166ea78cd9d0x827c87cc1954618962024-03-29 14:23:385 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000203 0.01
0x8c75d7174449df2439c8289e66b7a54f59858dac4e6b56d23fe9d2ffb1e184bf0xc8173c441954617462024-03-29 14:23:006 mins ago0x161baeceec8a61d78979f4d3fa8535a8eab1c6ea IN  0x25ab3efd52e6470681ce037cd546dc60726948d30.0175 ETH0.00000221 0.01
0xe574e1aa8aba8bd0757fe4deeeecd7199c82a4fc53ff99b20459cd9e4fc18c050xa5c9c66c1954614112024-03-29 14:21:357 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000252 0.01
0xc3ff34b185d9cc7c6d9643ab8188e277930c21a417d6911700d8a24101a98d690xa5c9c66c1954614002024-03-29 14:21:328 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000249 0.01
0xdc38f89c8e2b45f2959187dcfa926c205e0781ac0863fcc511aab69b7fe3d2f70xc8173c441954613912024-03-29 14:21:308 mins ago0x80fca40f0c9922128a63d1f66a2a6427691b72ca IN  0x25ab3efd52e6470681ce037cd546dc60726948d30.0017 ETH0.00000222 0.01
0xe751ea4d226ae6e8e187e5e36c079322138898b8e7a5d9784fe61fae8381d0910xab115fd81954613852024-03-29 14:21:298 mins ago0x666d6b8a44d226150ca9058beebafe0e3ac065a2 IN  0x25ab3efd52e6470681ce037cd546dc60726948d30 ETH0.00000193 0.01
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x2582b660b9a0a1d0b86044155b9027075e7859279902f7ced974609aa5ce54a61954625382024-03-29 14:26:213 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30xfc14afd56622a98c98e905e0299f5214081c53d70.012123 ETH
0xc2c491caa6185d819ff6a38436076e053676cf266be383c7a6d7ded21e1b36771954610022024-03-29 14:19:539 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30x3a6049789893ab83fc49e17b9b495499bb5ca7520.531071 ETH
0xe5977ef39a0780862c74e4ae5feb7e82aadabebed26c45e59c39e63018d7a2621954609882024-03-29 14:19:499 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30xc12fefca6bc523492a1cfafda227f15aa9ce6d1e0.001789 ETH
0x5047a7177423ce86bfb06b885ef22d63d5a4d8194472471878f36bd960300b401954587762024-03-29 14:10:3518 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30xc151071dfd5b66698b5d6b55607a63b9daebd6900.003089 ETH
0x2d304a220ebf7ac26f8980994dbe31f3c6cc4f2df851698a117742fd2c5435871954567632024-03-29 14:02:1127 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30x564e5d3665671acebadfcac6f194ed1bd2b41e2a0.003065 ETH
0x0c7063bd603c154b08dd3e6768913dab2c7d697f6430627daee9f6070e8a9e0d1954567252024-03-29 14:02:0127 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30x6c46aedf83b8e1585bab2f0396ee3bdcec1803810.011589 ETH
0x3721c04a1fa1a4e0a1564e021932c639cd604cb6f0c40b43179ea065b0738cec1954553282024-03-29 13:56:1233 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.027142 ETH
0x15e4b389b871a2ebb192cfa40932d7fe510ab78a267e2b6370082b8a76a306771954542792024-03-29 13:51:5137 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.017801 ETH
0x1d0848908fd7d41fc999d5a4b0ebdc08c644cab571a5977e6c5d37731f121f771954523602024-03-29 13:43:5045 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.003247 ETH
0xcdf7c3b811a52a73dbf0c86f15156e624eeb12f02def09bf7db6708024abc9701954512722024-03-29 13:39:1750 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30x3f4dd1b08c0a6b6a11787833bc4e5e34a646cea11.128747 ETH
0x8183a407fa54c51e22e62a7483d28c7bf404ff9dc5114a12545d18d4a014628d1954511852024-03-29 13:38:5550 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.004756 ETH
0x7c9e583d476457f07faa35be8476edfeb7f82f39ae5aabf9ebb1471ad356c55d1954506072024-03-29 13:36:2953 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.038656 ETH
0xcafd7eb7c5b0f7b2909d874470b6c7bc09f11de38d8c3f70db7bd6e82cb2011b1954503742024-03-29 13:35:3154 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.108518 ETH
0x4b4f6b927e5dd220fb4df7cf3221e960bfa3738d5890cce4aa648f2a9a94f9471954502232024-03-29 13:34:5354 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.003406 ETH
0xe449f0650b856da4ad22838b0e825588c7e67b56cd57a4f15ee69fec694252b11954500192024-03-29 13:34:0455 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.070549 ETH
0x5e03846b945318171c49b6a8f0d3adb978b81ccc0016be5099d2157389c7de801954491462024-03-29 13:30:2559 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30x7321f99d9e042f9ef88a775a2deb7ab32d17457f0.003488 ETH
0xb1864f98e2dbbbc9744f3cb05279325a42f95058d7361de2d59a8a71bd9afd861954491222024-03-29 13:30:1959 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30xd311b6d6947a9dbe8847110a6c11af867e2c302e0.202185 ETH
0x99578d36d47a34785337dd28b8b59bce2b06530977ea15e02773ab4f4f4ae9361954489622024-03-29 13:29:3959 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.011546 ETH
0x169c4e2c0e1135ec89cfbc7d383d90dd52af04e1186af7b7bf26b076aebd2de11954479832024-03-29 13:25:341 hr 3 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30x3249e920d6aefea58e132f678c9850c5e5434ce30.000389 ETH
0x2a92006d550b352f7a09c4372750365382c0f6b87a3baec08a86ef9fd4ccf5bc1954479522024-03-29 13:25:261 hr 4 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30x5e52b89cf1ef8be104cb11de2bee54f453e23e080.003488 ETH
0x2d6f9ecae23357a103af642d225592f7989478b741d02c4e52554a1a6f14470f1954469242024-03-29 13:21:111 hr 8 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30x648bc16e1f4c08504b0cdf4c4fe1b4ef7b0aa6d10.001489 ETH
0x617d6624f42c84886fb558c3af0142ea28361c49fbc8f3aa5c40cd515f2d7caf1954460662024-03-29 13:17:351 hr 11 mins ago 0x25ab3efd52e6470681ce037cd546dc60726948d30xbacde4d43f45f656928009345a6fe1c93bf465430.043464 ETH
0x6b6e6ef92e195ecb4ede5bcf70e0f7e8d70077fcc5c16309f0e42759f29533fd1954453422024-03-29 13:14:351 hr 14 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.003811 ETH
0x5c6a5762ad0bfb297111ad4f136afc06d03c29ef62af268d7b9e7c5d608484351954440142024-03-29 13:09:001 hr 20 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.002828 ETH
0x150cc022507f5cea7067a9d8e5e587c98b717368ca5436b45ce02ac8450a51b41954439692024-03-29 13:08:501 hr 20 mins ago 0x1b2fcf4dc785638cf33d24b166fd3d24cbb79315 0x25ab3efd52e6470681ce037cd546dc60726948d30.464834 ETH
[ Download CSV Export 
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
ProxyToMeson

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 10000 runs

Other Settings:
istanbul EvmVersion, MIT license
File 1 of 1 : Flattened.sol
// Sources flattened with hardhat v2.10.1 https://hardhat.org

// File @openzeppelin/contracts/proxy/[email protected]


// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)

pragma solidity ^0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}


// File @openzeppelin/contracts/proxy/beacon/[email protected]


// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}


// File @openzeppelin/contracts/interfaces/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822Proxiable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}


// File @openzeppelin/contracts/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File @openzeppelin/contracts/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }
}


// File @openzeppelin/contracts/proxy/ERC1967/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;




/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 *
 * @custom:oz-upgrades-unsafe-allow delegatecall
 */
abstract contract ERC1967Upgrade {
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Emitted when the beacon is upgraded.
     */
    event BeaconUpgraded(address indexed beacon);

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            Address.isContract(IBeacon(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(
        address newBeacon,
        bytes memory data,
        bool forceCall
    ) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        }
    }
}


// File @openzeppelin/contracts/proxy/ERC1967/[email protected]


// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)

pragma solidity ^0.8.0;


/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 */
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
     *
     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
     * function call, and allows initializing the storage of the proxy like a Solidity constructor.
     */
    constructor(address _logic, bytes memory _data) payable {
        _upgradeToAndCall(_logic, _data, false);
    }

    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal view virtual override returns (address impl) {
        return ERC1967Upgrade._getImplementation();
    }
}


// File @openzeppelin/contracts-upgradeable/interfaces/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822ProxiableUpgradeable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}


// File @openzeppelin/contracts-upgradeable/proxy/beacon/[email protected]


// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeaconUpgradeable {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}


// File @openzeppelin/contracts-upgradeable/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File @openzeppelin/contracts-upgradeable/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
 */
library StorageSlotUpgradeable {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }
}


// File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
     * initialization step. This is essential to configure modules that are added through upgrades and that require
     * initialization.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized < type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }
}


// File @openzeppelin/contracts-upgradeable/proxy/ERC1967/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;





/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 *
 * @custom:oz-upgrades-unsafe-allow delegatecall
 */
abstract contract ERC1967UpgradeUpgradeable is Initializable {
    function __ERC1967Upgrade_init() internal onlyInitializing {
    }

    function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
    }
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            _functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Emitted when the beacon is upgraded.
     */
    event BeaconUpgraded(address indexed beacon);

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(
        address newBeacon,
        bytes memory data,
        bool forceCall
    ) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
        }
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
        require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed");
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}


// File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol)

pragma solidity ^0.8.0;



/**
 * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
 * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
 *
 * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
 * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
 * `UUPSUpgradeable` with a custom implementation of upgrades.
 *
 * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
 *
 * _Available since v4.1._
 */
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
    function __UUPSUpgradeable_init() internal onlyInitializing {
    }

    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
    }
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
    address private immutable __self = address(this);

    /**
     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
     * fail.
     */
    modifier onlyProxy() {
        require(address(this) != __self, "Function must be called through delegatecall");
        require(_getImplementation() == __self, "Function must be called through active proxy");
        _;
    }

    /**
     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
     * callable on the implementing contract but not through proxies.
     */
    modifier notDelegated() {
        require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
        _;
    }

    /**
     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
     * implementation. It is used to validate that the this implementation remains valid after an upgrade.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
     */
    function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
        return _IMPLEMENTATION_SLOT;
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     */
    function upgradeTo(address newImplementation) external virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
     * encoded in `data`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     */
    function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, data, true);
    }

    /**
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
     * {upgradeTo} and {upgradeToAndCall}.
     *
     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
     *
     * ```solidity
     * function _authorizeUpgrade(address) internal override onlyOwner {}
     * ```
     */
    function _authorizeUpgrade(address newImplementation) internal virtual;

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}


// File contracts/Swap/IMesonSwapEvents.sol


pragma solidity 0.8.16;

/// @title MesonSwapEvents Interface
interface IMesonSwapEvents {
  /// @notice Event when a swap request was posted.
  /// Emit at the end of `postSwap()` calls.
  /// @param encodedSwap Encoded swap
  event SwapPosted(uint256 indexed encodedSwap);

  /// @notice Event when a swap request was bonded.
  /// Emit at the end of `bondSwap()` calls.
  /// @param encodedSwap Encoded swap
  event SwapBonded(uint256 indexed encodedSwap);

  /// @notice Event when a swap request was cancelled.
  /// Emit at the end of `cancelSwap()` calls.
  /// @param encodedSwap Encoded swap
  event SwapCancelled(uint256 indexed encodedSwap);
}


// File contracts/utils/MesonTokens.sol


pragma solidity 0.8.16;

/// @title MesonTokens
/// @notice The class that stores the information of Meson's supported tokens
contract MesonTokens {
  /// @notice The whitelist of supported tokens in Meson
  /// Meson use a whitelist for supported stablecoins, which is specified on first deployment
  /// or added through `_addSupportToken` Only modify this mapping through `_addSupportToken`.
  /// key: `tokenIndex` in range of 1-255; zero means unsupported
  /// value: the supported token's contract address
  mapping(uint8 => address) public tokenForIndex;


  /// @notice The mapping to get `tokenIndex` from a supported token's address
  /// Only modify this mapping through `_addSupportToken`.
  /// key: the supported token's contract address
  /// value: `tokenIndex` in range of 1-255; zero means unsupported
  mapping(address => uint8) public indexOfToken;

  /// @dev This empty reserved space is put in place to allow future versions to
  /// add new variables without shifting down storage in the inheritance chain.
  /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  uint256[50] private __gap;

  /// @notice Return all supported token addresses in an array ordered by `tokenIndex`
  /// This method will only return tokens with consecutive token indexes.
  function getSupportedTokens() external view returns (address[] memory tokens, uint8[] memory indexes) {
    uint8 i;
    uint8 num;
    for (i = 0; i < 255; i++) {
      if (tokenForIndex[i+1] != address(0)) {
        num++;
      }
    }
    tokens = new address[](num);
    indexes = new uint8[](num);
    uint8 j = 0;
    for (i = 0; i < 255; i++) {
      if (tokenForIndex[i+1] != address(0)) {
        tokens[j] = tokenForIndex[i+1];
        indexes[j] = i+1;
        j++;
      }
    }
  }

  function _addSupportToken(address token, uint8 index) internal {
    require(index != 0, "Cannot use 0 as token index");
    require(token != address(0), "Cannot use zero address");
    require(indexOfToken[token] == 0, "Token has been added before");
    require(tokenForIndex[index] == address(0), "Index has been used");
    indexOfToken[token] = index;
    tokenForIndex[index] = token;
  }
}


// File @openzeppelin/contracts/utils/[email protected]


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}


// File contracts/utils/IERC20Minimal.sol

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

/// @title Minimal ERC20 interface for Uniswap
/// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3
interface IERC20Minimal {
  /// @notice Returns the balance of a token
  /// @param account The account for which to look up the number of tokens it has, i.e. its balance
  /// @return The number of tokens held by the account
  function balanceOf(address account) external view returns (uint256);

  /// @notice Transfers the amount of token from the `msg.sender` to the recipient
  /// @param recipient The account that will receive the amount transferred
  /// @param amount The number of tokens to send from the sender to the recipient
  /// @return Returns true for a successful transfer, false for an unsuccessful transfer
  function transfer(address recipient, uint256 amount) external returns (bool);

  /// @notice Returns the current allowance given to a spender by an owner
  /// @param owner The account of the token owner
  /// @param spender The account of the token spender
  /// @return The current allowance granted by `owner` to `spender`
  function allowance(address owner, address spender) external view returns (uint256);

  /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount`
  /// @param spender The account which will be allowed to spend a given amount of the owners tokens
  /// @param amount The amount of tokens allowed to be used by `spender`
  /// @return Returns true for a successful approval, false for unsuccessful
  function approve(address spender, uint256 amount) external returns (bool);

  /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender`
  /// @param sender The account from which the transfer will be initiated
  /// @param recipient The recipient of the transfer
  /// @param amount The amount of the transfer
  /// @return Returns true for a successful transfer, false for unsuccessful
  function transferFrom(
      address sender,
      address recipient,
      uint256 amount
  ) external returns (bool);

  /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`.
  /// @param from The account from which the tokens were sent, i.e. the balance decreased
  /// @param to The account to which the tokens were sent, i.e. the balance increased
  /// @param value The amount of tokens that were transferred
  event Transfer(address indexed from, address indexed to, uint256 value);

  /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes.
  /// @param owner The account that approved spending of its tokens
  /// @param spender The account for which the spending allowance was modified
  /// @param value The new allowance from the owner to the spender
  event Approval(address indexed owner, address indexed spender, uint256 value);
}


// File contracts/utils/ITransferWithBeneficiary.sol


pragma solidity 0.8.16;

/// @title Interface for transferWithBeneficiary
interface ITransferWithBeneficiary {
  /// @notice Make a token transfer that the *signer* is paying tokens but benefits are given to the *beneficiary*
  /// @param token The contract address of the transferring token
  /// @param amount The amount of the transfer
  /// @param beneficiary The address that will receive benefits of this transfer
  /// @param data Extra data passed to the contract
  /// @return Returns true for a successful transfer.
  function transferWithBeneficiary(address token, uint256 amount, address beneficiary, uint64 data) external returns (bool);
}


// File contracts/utils/MesonConfig.sol


pragma solidity 0.8.16;

/// @notice Parameters of the Meson contract
/// for Arbitrum
contract MesonConfig {
  uint8 constant MESON_PROTOCOL_VERSION = 1;

  // Ref https://github.com/satoshilabs/slips/blob/master/slip-0044.md
  uint16 constant SHORT_COIN_TYPE = 0x2329;

  uint256 constant MAX_SWAP_AMOUNT = 1e11; // 100,000.000000 = 100k
  uint256 constant SERVICE_FEE_RATE = 10; // service fee = 10 / 10000 = 0.1%

  uint256 constant MIN_BOND_TIME_PERIOD = 1 hours;
  uint256 constant MAX_BOND_TIME_PERIOD = 2 hours;
  uint256 constant LOCK_TIME_PERIOD = 20 minutes;

  bytes28 constant ETH_SIGN_HEADER = bytes28("\x19Ethereum Signed Message:\n32");
  bytes28 constant ETH_SIGN_HEADER_52 = bytes28("\x19Ethereum Signed Message:\n52");
  bytes25 constant TRON_SIGN_HEADER = bytes25("\x19TRON Signed Message:\n32\n");
  bytes25 constant TRON_SIGN_HEADER_33 = bytes25("\x19TRON Signed Message:\n33\n");
  bytes25 constant TRON_SIGN_HEADER_53 = bytes25("\x19TRON Signed Message:\n53\n");

  bytes32 constant REQUEST_TYPE_HASH = keccak256("bytes32 Sign to request a swap on Meson");
  bytes32 constant RELEASE_TYPE_HASH = keccak256("bytes32 Sign to release a swap on Mesonaddress Recipient");

  bytes32 constant RELEASE_TO_TRON_TYPE_HASH = keccak256("bytes32 Sign to release a swap on Mesonaddress Recipient (tron address in hex format)");
}


// File contracts/utils/MesonHelpers.sol


pragma solidity 0.8.16;





/// @title MesonHelpers
/// @notice The class that provides helper functions for Meson protocol
contract MesonHelpers is MesonConfig, Context {
  bytes4 private constant ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)"));
  bytes4 private constant ERC20_TRANSFER_FROM_SELECTOR = bytes4(keccak256("transferFrom(address,address,uint256)"));

  modifier matchProtocolVersion(uint256 encodedSwap) {
    require(_versionFrom(encodedSwap) == MESON_PROTOCOL_VERSION, "Incorrect encoding version");
    _;
  }

  function getShortCoinType() external pure returns (bytes2) {
    return bytes2(SHORT_COIN_TYPE);
  }

  /// @notice Safe transfers tokens from Meson contract to a recipient
  /// for interacting with ERC20 tokens that do not consistently return true/false
  /// @param token The contract address of the token which will be transferred
  /// @param recipient The recipient of the transfer
  /// @param amount The value of the transfer (always in decimal 6)
  /// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol`
  function _safeTransfer(
    address token,
    address recipient,
    uint256 amount,
    uint8 tokenIndex
  ) internal {
    require(Address.isContract(token), "The given token address is not a contract");

    if (_needAdjustAmount(tokenIndex)) {
      amount *= 1e12;
    }
    (bool success, bytes memory data) = token.call(abi.encodeWithSelector(
      ERC20_TRANSFER_SELECTOR,
      recipient,
      amount
    ));
    require(success && (data.length == 0 || abi.decode(data, (bool))), "transfer failed");

    // The above do not support Tron, so need to switch to the next line if deploying to Tron
    // IERC20Minimal(token).transfer(recipient, amount);
  }

  /// @notice Transfer tokens to a contract using `transferWithBeneficiary`
  /// @param token The contract address of the token which will be transferred
  /// @param contractAddr The smart contract address that will receive transferring tokens
  /// @param beneficiary The beneficiary of `transferWithBeneficiary`
  /// @param amount The value of the transfer (always in decimal 6)
  /// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol`
  /// @param data Extra data passed to the contract
  function _transferToContract(
    address token,
    address contractAddr,
    address beneficiary,
    uint256 amount,
    uint8 tokenIndex,
    uint64 data
  ) internal {
    require(Address.isContract(token), "The given token address is not a contract");
    require(Address.isContract(contractAddr), "The given recipient address is not a contract");

    if (_needAdjustAmount(tokenIndex)) {
      amount *= 1e12;
    }
    IERC20Minimal(token).approve(contractAddr, amount);
    ITransferWithBeneficiary(contractAddr).transferWithBeneficiary(token, amount, beneficiary, data);
  }

  /// @notice Help the senders to transfer their assets to the Meson contract
  /// @param token The contract address of the token which will be transferred
  /// @param sender The sender of the transfer
  /// @param amount The value of the transfer (always in decimal 6)
  /// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol`
  function _unsafeDepositToken(
    address token,
    address sender,
    uint256 amount,
    uint8 tokenIndex
  ) internal {
    require(token != address(0), "Token not supported");
    require(amount > 0, "Amount must be greater than zero");
    require(Address.isContract(token), "The given token address is not a contract");

    if (_needAdjustAmount(tokenIndex)) {
      amount *= 1e12;
    }
    (bool success, bytes memory data) = token.call(abi.encodeWithSelector(
      ERC20_TRANSFER_FROM_SELECTOR,
      sender,
      address(this),
      amount
    ));
    require(success && (data.length == 0 || abi.decode(data, (bool))), "transferFrom failed");
  }

  /// @notice Determine if token has decimal 18 and therefore need to adjust amount
  /// @param tokenIndex The index of token. See `tokenForIndex` in `MesonTokens.sol`
  function _needAdjustAmount(uint8 tokenIndex) internal pure returns (bool) {
    return tokenIndex > 32 && tokenIndex < 255;
  }

  /// @notice Calculate `swapId` from `encodedSwap`, `initiator`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _getSwapId(uint256 encodedSwap, address initiator) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked(encodedSwap, initiator));
  }

  /// @notice Decode `version` from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _versionFrom(uint256 encodedSwap) internal pure returns (uint8) {
    return uint8(encodedSwap >> 248);
  }

  /// @notice Decode `amount` from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _amountFrom(uint256 encodedSwap) internal pure returns (uint256) {
    return (encodedSwap >> 208) & 0xFFFFFFFFFF;
  }

  /// @notice Calculate the service fee from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _serviceFee(uint256 encodedSwap) internal pure returns (uint256) {
    return _amountFrom(encodedSwap) * SERVICE_FEE_RATE / 10000; // Default to `serviceFee` = 0.1% * `amount`
  }

  /// @notice Decode `fee` (the fee for LPs) from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _feeForLp(uint256 encodedSwap) internal pure returns (uint256) {
    return (encodedSwap >> 88) & 0xFFFFFFFFFF;
  }

  /// @notice Decode `salt` from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _saltFrom(uint256 encodedSwap) internal pure returns (uint80) {
    return uint80(encodedSwap >> 128);
  }

  /// @notice Decode data from `salt`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _saltDataFrom(uint256 encodedSwap) internal pure returns (uint64) {
    return uint64(encodedSwap >> 128);
  }

  /// @notice Whether the swap should release to a 3rd-party integrated dapp contract
  /// See method `release` in `MesonPools.sol` for more details
  function _willTransferToContract(uint256 encodedSwap) internal pure returns (bool) {
    return (encodedSwap & 0x8000000000000000000000000000000000000000000000000000) == 0;
  }

  /// @notice Whether the swap needs to pay service fee
  /// See method `release` in `MesonPools.sol` for more details about the service fee
  function _feeWaived(uint256 encodedSwap) internal pure returns (bool) {
    return (encodedSwap & 0x4000000000000000000000000000000000000000000000000000) > 0;
  }
  
  /// @notice Whether the swap was signed in the non-typed manner (usually by hardware wallets)
  function _signNonTyped(uint256 encodedSwap) internal pure returns (bool) {
    return (encodedSwap & 0x0800000000000000000000000000000000000000000000000000) > 0;
  }

  /// @notice Decode `expireTs` from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _expireTsFrom(uint256 encodedSwap) internal pure returns (uint256) {
    return (encodedSwap >> 48) & 0xFFFFFFFFFF;
    // [Suggestion]: return uint40(encodedSwap >> 48);
  }

  /// @notice Decode the initial chain (`inChain`) from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _inChainFrom(uint256 encodedSwap) internal pure returns (uint16) {
    return uint16(encodedSwap >> 8);
  }

  /// @notice Decode the token index of initial chain (`inToken`) from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _inTokenIndexFrom(uint256 encodedSwap) internal pure returns (uint8) {
    return uint8(encodedSwap);
  }

  /// @notice Decode the target chain (`outChain`) from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _outChainFrom(uint256 encodedSwap) internal pure returns (uint16) {
    return uint16(encodedSwap >> 32);
  }

  /// @notice Decode the token index of target chain (`outToken`) from `encodedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  function _outTokenIndexFrom(uint256 encodedSwap) internal pure returns (uint8) {
    return uint8(encodedSwap >> 24);
  }

  /// @notice Decode `outToken` from `encodedSwap`, and encode it with `poolIndex` to `poolTokenIndex`.
  /// See variable `_balanceOfPoolToken` in `MesonStates.sol` for the defination of `poolTokenIndex`
  function _poolTokenIndexForOutToken(uint256 encodedSwap, uint40 poolIndex) internal pure returns (uint48) {
    return uint48((encodedSwap & 0xFF000000) << 16) | poolIndex;
  }

  /// @notice Decode `initiator` from `postedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `postedSwap`
  function _initiatorFromPosted(uint200 postedSwap) internal pure returns (address) {
    return address(uint160(postedSwap >> 40));
  }

  /// @notice Decode `poolIndex` from `postedSwap`
  /// See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `postedSwap`
  function _poolIndexFromPosted(uint200 postedSwap) internal pure returns (uint40) {
    return uint40(postedSwap);
  }
  
  /// @notice Encode `lockedSwap` from `until` and `poolIndex`
  /// See variable `_lockedSwaps` in `MesonPools.sol` for the defination of `lockedSwap`
  function _lockedSwapFrom(uint256 until, uint40 poolIndex) internal pure returns (uint80) {
    return (uint80(until) << 40) | poolIndex;
  }

  /// @notice Decode `poolIndex` from `lockedSwap`
  /// See variable `_lockedSwaps` in `MesonPools.sol` for the defination of `lockedSwap`
  function _poolIndexFromLocked(uint80 lockedSwap) internal pure returns (uint40) {
    return uint40(lockedSwap);
  }

  /// @notice Decode `until` from `lockedSwap`
  /// See variable `_lockedSwaps` in `MesonPools.sol` for the defination of `lockedSwap`
  function _untilFromLocked(uint80 lockedSwap) internal pure returns (uint256) {
    return uint256(lockedSwap >> 40);
  }

  /// @notice Encode `poolTokenIndex` from `tokenIndex` and `poolIndex`
  /// See variable `_balanceOfPoolToken` in `MesonStates.sol` for the defination of `poolTokenIndex`
  function _poolTokenIndexFrom(uint8 tokenIndex, uint40 poolIndex) internal pure returns (uint48) {
    return (uint48(tokenIndex) << 40) | poolIndex;
  }

  /// @notice Decode `tokenIndex` from `poolTokenIndex`
  /// See variable `_balanceOfPoolToken` in `MesonStates.sol` for the defination of `poolTokenIndex`
  function _tokenIndexFrom(uint48 poolTokenIndex) internal pure returns (uint8) {
    return uint8(poolTokenIndex >> 40);
  }

  /// @notice Decode `poolIndex` from `poolTokenIndex`
  /// See variable `_balanceOfPoolToken` in `MesonStates.sol` for the defination of `poolTokenIndex`
  function _poolIndexFrom(uint48 poolTokenIndex) internal pure returns (uint40) {
    return uint40(poolTokenIndex);
  }

  /// @notice Check the initiator's signature for a swap request
  /// Signatures are constructed with the package `mesonfi/sdk`. Go to `packages/sdk/src/SwapSigner.ts` and 
  /// see how to generate a signautre in class `EthersWalletSwapSigner` method `signSwapRequest`
  /// @param encodedSwap Encoded swap information. See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  /// @param r Part of the signature
  /// @param s Part of the signature
  /// @param v Part of the signature
  /// @param signer The signer for the swap request which is the `initiator`
  function _checkRequestSignature(
    uint256 encodedSwap,
    bytes32 r,
    bytes32 s,
    uint8 v,
    address signer
  ) internal pure {
    require(signer != address(0), "Signer cannot be empty address");
    require(v == 27 || v == 28, "Invalid signature");
    require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "Invalid signature");

    bool nonTyped = _signNonTyped(encodedSwap);
    bytes32 digest;
    if (_inChainFrom(encodedSwap) == 0x00c3) {
      digest = keccak256(abi.encodePacked(nonTyped ? TRON_SIGN_HEADER_33 : TRON_SIGN_HEADER, encodedSwap));
    } else if (nonTyped) {
      digest = keccak256(abi.encodePacked(ETH_SIGN_HEADER, encodedSwap));
    } else {
      bytes32 typehash = REQUEST_TYPE_HASH;
      assembly {
        mstore(0, encodedSwap)
        mstore(32, keccak256(0, 32))
        mstore(0, typehash)
        digest := keccak256(0, 64)
      }
    }
    require(signer == ecrecover(digest, v, r, s), "Invalid signature");
  }

  /// @notice Check the initiator's signature for the release request
  /// Signatures are constructed with the package `mesonfi/sdk`. Go to `packages/sdk/src/SwapSigner.ts` and 
  /// see how to generate a signautre in class `EthersWalletSwapSigner` method `signSwapRelease`
  /// @param encodedSwap Encoded swap information. See variable `_postedSwaps` in `MesonSwap.sol` for the defination of `encodedSwap`
  /// @param recipient The recipient address of the swap
  /// @param r Part of the signature
  /// @param s Part of the signature
  /// @param v Part of the signature
  /// @param signer The signer for the swap request which is the `initiator`
  function _checkReleaseSignature(
    uint256 encodedSwap,
    address recipient,
    bytes32 r,
    bytes32 s,
    uint8 v,
    address signer
  ) internal pure {
    require(signer != address(0), "Signer cannot be empty address");
    require(v == 27 || v == 28, "Invalid signature");
    require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "Invalid signature");

    bool nonTyped = _signNonTyped(encodedSwap);
    bytes32 digest;
    if (_inChainFrom(encodedSwap) == 0x00c3) {
      digest = keccak256(abi.encodePacked(nonTyped ? TRON_SIGN_HEADER_53 : TRON_SIGN_HEADER, encodedSwap, recipient));
    } else if (nonTyped) {
      digest = keccak256(abi.encodePacked(ETH_SIGN_HEADER_52, encodedSwap, recipient));
    } else {
      bytes32 typehash = _outChainFrom(encodedSwap) == 0x00c3 ? RELEASE_TO_TRON_TYPE_HASH : RELEASE_TYPE_HASH;
      assembly {
        mstore(20, recipient)
        mstore(0, encodedSwap)
        mstore(32, keccak256(0, 52))
        mstore(0, typehash)
        digest := keccak256(0, 64)
      }
    }
    require(signer == ecrecover(digest, v, r, s), "Invalid signature");
  }
}


// File contracts/utils/MesonStates.sol


pragma solidity 0.8.16;


/// @title MesonStates
/// @notice The class that keeps track of LP pool states
contract MesonStates is MesonTokens, MesonHelpers {
  /// @notice The mapping from *authorized addresses* to LP pool indexes.
  /// See `ownerOfPool` to understand how pool index is defined and used.
  ///
  /// This mapping records the relation between *authorized addresses* and pool indexes, where
  /// authorized addresses are those who have the permision to match and complete a swap with funds 
  /// in a pool with specific index. For example, for an LP pool with index `i` there could be multiple
  /// addresses that `poolOfAuthorizedAddr[address] = i`, which means these addresses can all sign to match
  /// (call `bondSwap`, `lock`) a swap and complete it (call `release`) with funds in pool `i`. That helps
  /// an LP to give other addresses the permission to perform daily swap transactions. However, authorized
  /// addresses cannot withdraw funds from the LP pool, unless it's given in `ownerOfPool` which records
  /// the *owner* address for each pool.
  ///
  /// The pool index 0 is reserved for use by Meson
  mapping(address => uint40) public poolOfAuthorizedAddr;

  /// @notice The mapping from LP pool indexes to their owner addresses.
  /// Each LP pool in Meson has a uint40 index `i` and each LP needs to register an pool index at
  /// initial deposit by calling `depositAndRegister`. The balance for each LP pool is tracked by its
  /// pool index and token index (see `_balanceOfPoolToken`).
  /// 
  /// This mapping records the *owner* address for each LP pool. Only the owner address can withdraw funds
  /// from its corresponding LP pool.
  ///
  /// The pool index 0 is reserved for use by Meson
  mapping(uint40 => address) public ownerOfPool;

  /// @notice Balance for each token in LP pool, tracked by the `poolTokenIndex`.
  /// See `ownerOfPool` to understand how pool index is defined and used.
  ///
  /// The balance of a token in an LP pool is `_balanceOfPoolToken[poolTokenIndex]` in which
  /// the `poolTokenIndex` is in format of `tokenIndex:uint8|poolIndex:uint40`. `tokenIndex`
  /// is the index of supported tokens given by `tokenForIndex` (see definition in `MesonTokens.sol`).
  /// The balances are always store as tokens have decimal 6, which is the case for USDC/USDT on most chains
  /// except BNB Chain & Conflux. In the exceptional cases, the value of token amount will be converted
  /// on deposit and withdrawal (see `_safeTransfer` and `_unsafeDepositToken` in `MesonHelpers.sol`).
  ///
  /// The pool index 0 is reserved for use by Meson to store service fees
  mapping(uint48 => uint256) internal _balanceOfPoolToken;

  /// @dev This empty reserved space is put in place to allow future versions to
  /// add new variables without shifting down storage in the inheritance chain.
  /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  uint256[50] private __gap;

  function poolTokenBalance(address token, address addr) external view returns (uint256) {
    uint8 tokenIndex = indexOfToken[token];
    uint40 poolIndex = poolOfAuthorizedAddr[addr];
    if (poolIndex == 0 || tokenIndex == 0) {
      return 0;
    }
    return _balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, poolIndex)];
  }
  
  /// @notice The collected service fee of a specific token.
  /// @param tokenIndex The index of a supported token. See `tokenForIndex` in `MesonTokens.sol`
  function serviceFeeCollected(uint8 tokenIndex) external view returns (uint256) {
    return _balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, 0)];
  }
}


// File contracts/Swap/MesonSwap.sol


pragma solidity 0.8.16;


/// @title MesonSwap
/// @notice The class to receive and process swap requests on the initial chain side.
/// Methods in this class will be executed by swap initiators or LPs
/// on the initial chain of swaps.
contract MesonSwap is IMesonSwapEvents, MesonStates {
  /// @notice Posted Swaps
  /// key: `encodedSwap` in format of `version:uint8|amount:uint40|salt:uint80|fee:uint40|expireTs:uint40|outChain:uint16|outToken:uint8|inChain:uint16|inToken:uint8`
  ///   version: Version of encoding
  ///   amount: The amount of tokens of this swap, always in decimal 6. The amount of a swap is capped at $100k so it can be safely encoded in uint48;
  ///   salt: The salt value of this swap, carrying some information below:
  ///     salt & 0x80000000000000000000 == true => will release to an owa address, otherwise a smart contract;
  ///     salt & 0x40000000000000000000 == true => will waive *service fee*;
  ///     salt & 0x08000000000000000000 == true => use *non-typed signing* (some wallets such as hardware wallets don't support EIP-712v1);
  ///     salt & 0x0000ffffffffffffffff: customized data that can be passed to integrated 3rd-party smart contract;
  ///   fee: The fee given to LPs (liquidity providers). An extra service fee maybe charged afterwards;
  ///   expireTs: The expiration time of this swap on the initial chain. The LP should `executeSwap` and receive his funds before `expireTs`;
  ///   outChain: The target chain of a cross-chain swap (given by the last 2 bytes of SLIP-44);
  ///   outToken: The index of the token on the target chain. See `tokenForIndex` in `MesonToken.sol`;
  ///   inChain: The initial chain of a cross-chain swap (given by the last 2 bytes of SLIP-44);
  ///   inToken: The index of the token on the initial chain. See `tokenForIndex` in `MesonToken.sol`.
  /// value: `postedSwap` in format of `initiator:address|poolIndex:uint40`
  ///   initiator: The swap initiator who created and signed the swap request (not necessarily the one who posted the swap);
  //    poolIndex: The index of an LP pool. See `ownerOfPool` in `MesonStates.sol` for more information.
  mapping(uint256 => uint200) internal _postedSwaps;

  /// @dev This empty reserved space is put in place to allow future versions to
  /// add new variables without shifting down storage in the inheritance chain.
  /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  uint256[50] private __gap;

  /// @notice Anyone can call this method to post a swap request. This is step 1️⃣ in a swap.
  /// The r,s,v signature must be signed by the swap initiator. The initiator can call
  /// this method directly, in which case `poolIndex` should be zero and wait for LPs
  /// to call `bondSwap`. Initiators can also send the swap requests offchain (through the
  /// meson relayer service). An LP (pool owner or authorized addresses) who receives requests through
  /// the relayer can call this method to post and bond the swap in a single contract execution,
  /// in which case he should give his own `poolIndex`.
  ///
  /// The swap will last until `expireTs` and at most one LP pool can bond to it.
  /// After the swap expires, the initiator can cancel the swap and withdraw funds.
  ///
  /// Once a swap is posted and bonded, the bonding LP should call `lock` on the target chain.
  ///
  /// @dev Designed to be used by both swap initiators, pool owner, or authorized addresses
  /// @param encodedSwap Encoded swap information; also used as the key of `_postedSwaps`
  /// @param r Part of the signature
  /// @param s Part of the signature
  /// @param v Part of the signature
  /// @param postingValue The value to be written to `_postedSwaps`. See `_postedSwaps` for encoding format
  function postSwap(uint256 encodedSwap, bytes32 r, bytes32 s, uint8 v, uint200 postingValue)
    external matchProtocolVersion(encodedSwap) forInitialChain(encodedSwap)
  {
    require(_postedSwaps[encodedSwap] == 0, "Swap already exists");

    uint256 amount = _amountFrom(encodedSwap);
    require(amount <= MAX_SWAP_AMOUNT, "For security reason, amount cannot be greater than 100k");

    uint256 delta = _expireTsFrom(encodedSwap) - block.timestamp;
    // Underflow would trigger "Expire ts too late" error
    require(delta > MIN_BOND_TIME_PERIOD, "Expire ts too early");
    require(delta < MAX_BOND_TIME_PERIOD, "Expire ts too late");

    uint40 poolIndex = _poolIndexFromPosted(postingValue);
    if (poolIndex > 0) {
      // In pool index is given, the signer should be an authorized address
      require(poolOfAuthorizedAddr[_msgSender()] == poolIndex, "Signer should be an authorized address of the given pool");
    } // Otherwise, this is posted without bonding to a specific pool. Need to execute `bondSwap` later

    address initiator = _initiatorFromPosted(postingValue);
    _checkRequestSignature(encodedSwap, r, s, v, initiator);
    _postedSwaps[encodedSwap] = postingValue;

    uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
    _unsafeDepositToken(tokenForIndex[tokenIndex], initiator, amount, tokenIndex);

    emit SwapPosted(encodedSwap);
  }

  /// @notice If `postSwap` is called by the initiator of the swap and `poolIndex`
  /// is zero, an LP (pool owner or authorized addresses) can call this to bond the swap to himself.
  /// @dev Designed to be used by pool owner or authorized addresses
  /// @param encodedSwap Encoded swap information; also used as the key of `_postedSwaps`
  /// @param poolIndex The index of an LP pool. See `ownerOfPool` in `MesonStates.sol` for more information.
  function bondSwap(uint256 encodedSwap, uint40 poolIndex) external {
    uint200 postedSwap = _postedSwaps[encodedSwap];
    require(postedSwap > 1, "Swap does not exist");
    require(_poolIndexFromPosted(postedSwap) == 0, "Swap bonded to another pool");
    require(poolOfAuthorizedAddr[_msgSender()] == poolIndex, "Signer should be an authorized address of the given pool");

    _postedSwaps[encodedSwap] = postedSwap | poolIndex;
    emit SwapBonded(encodedSwap);
  }

  /// @notice Cancel a swap. The swap initiator can call this method to withdraw funds
  /// from an expired swap request.
  /// @dev Designed to be used by swap initiators
  /// @param encodedSwap Encoded swap information; also used as the key of `_postedSwaps`
  function cancelSwap(uint256 encodedSwap) external {
    uint200 postedSwap = _postedSwaps[encodedSwap];
    require(postedSwap > 1, "Swap does not exist");
    require(_expireTsFrom(encodedSwap) < block.timestamp, "Swap is still locked");

    _postedSwaps[encodedSwap] = 0; // Swap expired so the same one cannot be posted again

    uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
    _safeTransfer(tokenForIndex[tokenIndex], _initiatorFromPosted(postedSwap), _amountFrom(encodedSwap), tokenIndex);

    emit SwapCancelled(encodedSwap);
  }

  /// @notice Execute the swap by providing a release signature. This is step 4️⃣ in a swap.
  /// Once the signature is verified, the current bonding pool will receive funds deposited 
  /// by the swap initiator.
  /// @dev Designed to be used by pool owner or authorized addresses of the current bonding pool
  /// @param encodedSwap Encoded swap information; also used as the key of `_postedSwaps`
  /// @param r Part of the release signature (same as in the `release` call)
  /// @param s Part of the release signature (same as in the `release` call)
  /// @param v Part of the release signature (same as in the `release` call)
  /// @param recipient The recipient address of the swap
  /// @param depositToPool Whether to deposit funds to the pool (will save gas)
  function executeSwap(
    uint256 encodedSwap,
    bytes32 r,
    bytes32 s,
    uint8 v,
    address recipient,
    bool depositToPool
  ) external {
    uint200 postedSwap = _postedSwaps[encodedSwap];
    require(postedSwap > 1, "Swap does not exist");

    // Swap expiredTs < current + MIN_BOND_TIME_PERIOD
    if (_expireTsFrom(encodedSwap) < block.timestamp + MIN_BOND_TIME_PERIOD) {
      // The swap cannot be posted again and therefore safe to remove it.
      // LPs who execute in this mode can save ~5000 gas.
      _postedSwaps[encodedSwap] = 0;
    } else {
      // The same swap information can be posted again, so set `_postedSwaps` value to 1 to prevent that.
      _postedSwaps[encodedSwap] = 1;
    }

    _checkReleaseSignature(encodedSwap, recipient, r, s, v, _initiatorFromPosted(postedSwap));

    uint8 tokenIndex = _inTokenIndexFrom(encodedSwap);
    uint40 poolIndex = _poolIndexFromPosted(postedSwap);
    if (depositToPool) {
      _balanceOfPoolToken[_poolTokenIndexFrom(tokenIndex, poolIndex)] += _amountFrom(encodedSwap);
    } else {
      _safeTransfer(tokenForIndex[tokenIndex], ownerOfPool[poolIndex], _amountFrom(encodedSwap), tokenIndex);
    }
  }

  /// @notice Read information for a posted swap
  function getPostedSwap(uint256 encodedSwap) external view
    returns (address initiator, address poolOwner, bool exist)
  {
    uint200 postedSwap = _postedSwaps[encodedSwap];
    initiator = _initiatorFromPosted(postedSwap);
    exist = postedSwap > 0;
    if (initiator == address(0)) {
      poolOwner = address(0);
    } else {
      poolOwner = ownerOfPool[_poolIndexFromPosted(postedSwap)];
    }
  }

  modifier forInitialChain(uint256 encodedSwap) {
    require(_inChainFrom(encodedSwap) == SHORT_COIN_TYPE, "Swap not for this chain");
    _;
  }
}


// File contracts/Pools/IMesonPoolsEvents.sol


pragma solidity 0.8.16;

/// @title MesonPools Interface
interface IMesonPoolsEvents {
  /// @notice Event when an LP pool is registered.
  /// Emit at the end of `depositAndRegister()` calls.
  /// @param poolIndex Pool index
  /// @param owner Pool owner
  event PoolRegistered(uint40 indexed poolIndex, address owner);

  /// @notice Event when fund was deposited to an LP pool.
  /// Emit at the end of `depositAndRegister()` and `deposit()` calls.
  /// @param poolTokenIndex Concatenation of pool index & token index
  /// @param amount The amount of tokens to be added to the pool
  event PoolDeposited(uint48 indexed poolTokenIndex, uint256 amount);

  /// @notice Event when fund was withdrawn from an LP pool.
  /// Emit at the end of `withdraw()` calls.
  /// @param poolTokenIndex Concatenation of pool index & token index
  /// @param amount The amount of tokens to be removed from the pool
  event PoolWithdrawn(uint48 indexed poolTokenIndex, uint256 amount);

  /// @notice Event when an authorized address was added for an LP pool.
  /// Emit at the end of `depositAndRegister()` calls.
  /// @param poolIndex Pool index
  /// @param addr Authorized address to be added
  event PoolAuthorizedAddrAdded(uint40 indexed poolIndex, address addr);

  /// @notice Event when an authorized address was removed for an LP pool.
  /// Emit at the end of `depositAndRegister()` calls.
  /// @param poolIndex Pool index
  /// @param addr Authorized address to be removed
  event PoolAuthorizedAddrRemoved(uint40 indexed poolIndex, address addr);

  /// @notice Event when a swap was locked.
  /// Emit at the end of `lock()` calls.
  /// @param encodedSwap Encoded swap
  event SwapLocked(uint256 indexed encodedSwap);

  /// @notice Event when a swap was unlocked.
  /// Emit at the end of `unlock()` calls.
  /// @param encodedSwap Encoded swap
  event SwapUnlocked(uint256 indexed encodedSwap);

  /// @notice Event when a swap was released.
  /// Emit at the end of `release()` calls.
  /// @param encodedSwap Encoded swap
  event SwapReleased(uint256 indexed encodedSwap);
}


// File contracts/Pools/MesonPools.sol


pragma solidity 0.8.16;


/// @title MesonPools
/// @notice The class to manage pools for LPs, and perform swap operations on the target 
/// chain side.
/// Methods in this class will be executed when a user wants to swap into this chain.
/// LP pool operations are also provided in this class.
contract MesonPools is IMesonPoolsEvents, MesonStates {
  /// @notice Locked Swaps
  /// key: `swapId` is calculated from `encodedSwap` and `initiator`. See `_getSwapId` in `MesonHelpers.sol`
  ///   encodedSwap: see `MesonSwap.sol` for defination;
  ///   initiator: The user address who created and signed the swap request.
  /// value: `lockedSwap` in format of `until:uint40|poolIndex:uint40`
  ///   until: The expiration time of this swap on the target chain. Need to `release` the swap fund before `until`;
  ///   poolIndex: The index of an LP pool. See `ownerOfPool` in `MesonStates.sol` for more information.
  mapping(bytes32 => uint80) internal _lockedSwaps;

  /// @dev This empty reserved space is put in place to allow future versions to
  /// add new variables without shifting down storage in the inheritance chain.
  /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  uint256[50] private __gap;

  /// @notice Initially deposit tokens into an LP pool and register a pool index.
  /// This is the prerequisite for LPs if they want to participate in Meson swaps.
  /// @dev Designed to be used by a new address who wants to be an LP and register a pool index
  /// @param amount The amount of tokens to be added to the pool
  /// @param poolTokenIndex In format of `tokenIndex:uint8|poolIndex:uint40`. See `_balanceOfPoolToken` in `MesonStates.sol` for more information.
  function depositAndRegister(uint256 amount, uint48 poolTokenIndex) external {
    require(amount > 0, "Amount must be positive");

    address poolOwner = _msgSender();
    uint40 poolIndex = _poolIndexFrom(poolTokenIndex);
    require(poolIndex != 0, "Cannot use 0 as pool index"); // pool 0 is reserved for meson service fee
    require(ownerOfPool[poolIndex] == address(0), "Pool index already registered");
    require(poolOfAuthorizedAddr[poolOwner] == 0, "Signer address already registered");
    ownerOfPool[poolIndex] = poolOwner;
    poolOfAuthorizedAddr[poolOwner] = poolIndex;

    _balanceOfPoolToken[poolTokenIndex] += amount;
    uint8 tokenIndex = _tokenIndexFrom(poolTokenIndex);
    _unsafeDepositToken(tokenForIndex[tokenIndex], poolOwner, amount, tokenIndex);

    emit PoolRegistered(poolIndex, poolOwner);
    emit PoolDeposited(poolTokenIndex, amount);
  }

  /// @notice Deposit tokens into the liquidity pool.
  /// The LP should be careful to make sure the `poolTokenIndex` is correct.
  /// Make sure to call `depositAndRegister` first and register a pool index.
  /// Otherwise, token may be deposited to others.
  /// @dev Designed to be used by addresses authorized to a pool
  /// @param amount The amount of tokens to be added to the pool
  /// @param poolTokenIndex In format of `tokenIndex:uint8|poolIndex:uint40`. See `_balanceOfPoolToken` in `MesonStates.sol` for more information.
  function deposit(uint256 amount, uint48 poolTokenIndex) external {
    require(amount > 0, "Amount must be positive");

    uint40 poolIndex = _poolIndexFrom(poolTokenIndex);
    require(poolIndex != 0, "Cannot use 0 as pool index"); // pool 0 is reserved for meson service fee
    require(poolIndex == poolOfAuthorizedAddr[_msgSender()], "Need an authorized address as the signer");
    _balanceOfPoolToken[poolTokenIndex] += amount;
    uint8 tokenIndex = _tokenIndexFrom(poolTokenIndex);
    _unsafeDepositToken(tokenForIndex[tokenIndex], _msgSender(), amount, tokenIndex);

    emit PoolDeposited(poolTokenIndex, amount);
  }

  /// @notice Withdraw tokens from the liquidity pool.
  /// @dev Designed to be used by LPs (pool owners) who have already registered a pool index
  /// @param amount The amount to be removed from the pool
  /// @param poolTokenIndex In format of `tokenIndex:uint8|poolIndex:uint40. See `_balanceOfPoolToken` in `MesonStates.sol` for more information.
  function withdraw(uint256 amount, uint48 poolTokenIndex) external {
    require(amount > 0, "Amount must be positive");

    uint40 poolIndex = _poolIndexFrom(poolTokenIndex);
    require(poolIndex != 0, "Cannot use 0 as pool index"); // pool 0 is reserved for meson service fee
    require(ownerOfPool[poolIndex] == _msgSender(), "Need the pool owner as the signer");
    _balanceOfPoolToken[poolTokenIndex] -= amount;
    uint8 tokenIndex = _tokenIndexFrom(poolTokenIndex);
    _safeTransfer(tokenForIndex[tokenIndex], _msgSender(), amount, tokenIndex);

    emit PoolWithdrawn(poolTokenIndex, amount);
  }

  /// @notice Add an authorized address to the pool
  /// @dev Designed to be used by LPs (pool owners)
  /// @param addr The address to be added
  function addAuthorizedAddr(address addr) external {
    require(poolOfAuthorizedAddr[addr] == 0, "Addr is authorized for another pool");
    address poolOwner = _msgSender();
    uint40 poolIndex = poolOfAuthorizedAddr[poolOwner];
    require(poolIndex != 0, "The signer does not register a pool");
    require(poolOwner == ownerOfPool[poolIndex], "Need the pool owner as the signer");
    poolOfAuthorizedAddr[addr] = poolIndex;

    emit PoolAuthorizedAddrAdded(poolIndex, addr);
  }
  
  /// @notice Remove an authorized address from the pool
  /// @dev Designed to be used by LPs (pool owners)
  /// @param addr The address to be removed
  function removeAuthorizedAddr(address addr) external {
    address poolOwner = _msgSender();
    uint40 poolIndex = poolOfAuthorizedAddr[poolOwner];
    require(poolIndex != 0, "The signer does not register a pool");
    require(poolOwner == ownerOfPool[poolIndex], "Need the pool owner as the signer");
    require(poolOfAuthorizedAddr[addr] == poolIndex, "Addr is not authorized for the signer's pool");
    poolOfAuthorizedAddr[addr] = 0;

    emit PoolAuthorizedAddrRemoved(poolIndex, addr);
  }

  /// @notice Lock funds to match a swap request. This is step 2️⃣ in a swap.
  /// The authorized address of the bonding pool should call this method with
  /// the same signature given by `postSwap`. This method will lock swapping fund 
  /// on the target chain for `LOCK_TIME_PERIOD` and wait for fund release and 
  /// execution.
  /// @dev Designed to be used by authorized addresses or pool owners
  /// @param encodedSwap Encoded swap information
  /// @param r Part of the signature (the one given by `postSwap` call)
  /// @param s Part of the signature (the one given by `postSwap` call)
  /// @param v Part of the signature (the one given by `postSwap` call)
  /// @param initiator The swap initiator who created and signed the swap request
  function lock(
    uint256 encodedSwap,
    bytes32 r,
    bytes32 s,
    uint8 v,
    address initiator
  ) external matchProtocolVersion(encodedSwap) forTargetChain(encodedSwap) {
    bytes32 swapId = _getSwapId(encodedSwap, initiator);
    require(_lockedSwaps[swapId] == 0, "Swap already exists");
    _checkRequestSignature(encodedSwap, r, s, v, initiator);

    uint40 poolIndex = poolOfAuthorizedAddr[_msgSender()];
    require(poolIndex != 0, "Caller not registered. Call depositAndRegister.");

    uint256 until = block.timestamp + LOCK_TIME_PERIOD;
    require(until < _expireTsFrom(encodedSwap) - 5 minutes, "Cannot lock because expireTs is soon.");

    uint48 poolTokenIndex = _poolTokenIndexForOutToken(encodedSwap, poolIndex);
    // Only (amount - lp fee) is locked from the LP pool. The service fee will be charged on release
    _balanceOfPoolToken[poolTokenIndex] -= (_amountFrom(encodedSwap) - _feeForLp(encodedSwap));
    
    _lockedSwaps[swapId] = _lockedSwapFrom(until, poolIndex);

    emit SwapLocked(encodedSwap);
  }

  /// @notice If the locked swap is not released after `LOCK_TIME_PERIOD`,
  /// the authorized address can call this method to unlock the swapping fund.
  /// @dev Designed to be used by authorized addresses or pool owners
  /// @param encodedSwap Encoded swap information
  /// @param initiator The swap initiator who created and signed the swap request
  function unlock(uint256 encodedSwap, address initiator) external {
    bytes32 swapId = _getSwapId(encodedSwap, initiator);
    uint80 lockedSwap = _lockedSwaps[swapId];
    require(lockedSwap != 0, "Swap does not exist");
    require(_untilFromLocked(lockedSwap) < block.timestamp, "Swap still in lock");

    uint48 poolTokenIndex = _poolTokenIndexForOutToken(encodedSwap, _poolIndexFromLocked(lockedSwap));
    // (amount - lp fee) will be returned because only that amount was locked
    _balanceOfPoolToken[poolTokenIndex] += (_amountFrom(encodedSwap) - _feeForLp(encodedSwap));
    _lockedSwaps[swapId] = 0;

    emit SwapUnlocked(encodedSwap);
  }

  /// @notice Release tokens to satisfy a locked swap. This is step 3️⃣ in a swap.
  /// This method requires a release signature from the swap initiator,
  /// but anyone (initiator herself, the LP, and other people) with the signature 
  /// can call this method to make sure the swapping fund is guaranteed to be released.
  /// @dev Designed to be used by anyone
  /// @param encodedSwap Encoded swap information
  /// @param r Part of the release signature (same as in the `executeSwap` call)
  /// @param s Part of the release signature (same as in the `executeSwap` call)
  /// @param v Part of the release signature (same as in the `executeSwap` call)
  /// @param initiator The swap initiator who created and signed the swap request
  /// @param recipient The recipient address of the swap
  function release(
    uint256 encodedSwap,
    bytes32 r,
    bytes32 s,
    uint8 v,
    address initiator,
    address recipient
  ) external {
    bool feeWaived = _feeWaived(encodedSwap);
    if (feeWaived) {
      // For swaps that service fee is waived, need the premium manager as the signer
      _onlyPremiumManager();
    }
    // For swaps that charge service fee, anyone can call

    bytes32 swapId = _getSwapId(encodedSwap, initiator);
    uint80 lockedSwap = _lockedSwaps[swapId];
    require(lockedSwap != 0, "Swap does not exist");
    require(recipient != address(0), "Recipient cannot be zero address");
    require(_expireTsFrom(encodedSwap) > block.timestamp, "Cannot release because expired");

    _checkReleaseSignature(encodedSwap, recipient, r, s, v, initiator);
    _lockedSwaps[swapId] = 0;

    uint8 tokenIndex = _outTokenIndexFrom(encodedSwap);
    
    // LP fee will be subtracted from the swap amount
    uint256 releaseAmount = _amountFrom(encodedSwap) - _feeForLp(encodedSwap);
    if (!feeWaived) { // If the swap should pay service fee (charged by Meson protocol)
      uint256 serviceFee = _serviceFee(encodedSwap);
      // Subtract service fee from the release amount
      releaseAmount -= serviceFee;
      // Collected service fee will be stored in `_balanceOfPoolToken` with `poolIndex = 0`.
      // Currently, no one is capable to withdraw fund from pool 0. In the future, Meson protocol
      // will specify the purpose of service fee and its usage permission, and upgrade the contract
      // accordingly.
      _balanceOfPoolToken[_poolTokenIndexForOutToken(encodedSwap, 0)] += serviceFee;
    }

    _release(encodedSwap, tokenIndex, initiator, recipient, releaseAmount);

    emit SwapReleased(encodedSwap);
  }

  function _release(uint256 encodedSwap, uint8 tokenIndex, address initiator, address recipient, uint256 amount) private {
    if (_willTransferToContract(encodedSwap)) {
      _transferToContract(tokenForIndex[tokenIndex], recipient, initiator, amount, tokenIndex, _saltDataFrom(encodedSwap));
    } else {
      _safeTransfer(tokenForIndex[tokenIndex], recipient, amount, tokenIndex);
    }
  }

  /// @notice Read information for a locked swap
  function getLockedSwap(uint256 encodedSwap, address initiator) external view
    returns (address poolOwner, uint40 until)
  {
    bytes32 swapId = _getSwapId(encodedSwap, initiator);
    uint80 lockedSwap = _lockedSwaps[swapId];
    poolOwner = ownerOfPool[_poolIndexFromLocked(lockedSwap)];
    until = uint40(_untilFromLocked(lockedSwap));
  }

  modifier forTargetChain(uint256 encodedSwap) {
    require(_outChainFrom(encodedSwap) == SHORT_COIN_TYPE, "Swap not for this chain");
    _;
  }

  function _onlyPremiumManager() internal view virtual {}
}


// File contracts/MesonManager.sol


pragma solidity 0.8.16;


/// @title MesonManager
/// @notice The class to store data related to management permissions of Meson
contract MesonManager is MesonSwap, MesonPools {
  /// @notice The admin of meson contract
  /// The owner has the permission to upgrade meson contract. In future versions,
  /// the management authority of meson contract will be decentralized.
  address internal _owner;

  /// @notice The manager to authorized fee waived swaps
  /// Only the premium manager can authorize the execution to release for fee waived swaps.
  /// This address is managed by Meson team.
  address internal _premiumManager;

  /// @dev This empty reserved space is put in place to allow future versions to
  /// add new variables without shifting down storage in the inheritance chain.
  /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  uint256[50] private __gap;

  event OwnerTransferred(address indexed prevOwner, address indexed newOwner);

  event PremiumManagerTransferred(address indexed prevPremiumManager, address indexed newPremiumManager);

  /// @notice The owner will also have the permission to add supported tokens
  function addSupportToken(address token, uint8 index) external onlyOwner {
    _addSupportToken(token, index);
  }

  /// @notice Add multiple tokens
  function addMultipleSupportedTokens(address[] memory tokens, uint8[] memory indexes) external onlyOwner {
    require(tokens.length == indexes.length, "Tokens and indexes should have the same length");
    for (uint8 i = 0; i < tokens.length; i++) {
      _addSupportToken(tokens[i], indexes[i]);
    }
  }

  function transferOwnership(address newOwner) public onlyOwner {
    _transferOwnership(newOwner);
  }

  function transferPremiumManager(address newPremiumManager) public {
    _onlyPremiumManager();
    _transferPremiumManager(newPremiumManager);
  }

  modifier onlyOwner() {
    require(_owner == _msgSender(), "Caller is not the owner");
    _;
  }

  function _transferOwnership(address newOwner) internal {
    require(newOwner != address(0), "New owner cannot be zero address");
    address prevOwner = _owner;
    _owner = newOwner;
    emit OwnerTransferred(prevOwner, newOwner);
  }

  function _onlyPremiumManager() internal view override {
    require(_premiumManager == _msgSender(), "Caller is not the premium manager");
  }

  function _transferPremiumManager(address newPremiumManager) internal {
    require(newPremiumManager != address(0), "New premium manager be zero address");
    address prevPremiumManager = _premiumManager;
    _premiumManager = newPremiumManager;
    emit PremiumManagerTransferred(prevPremiumManager, newPremiumManager);
  }
}


// File contracts/UpgradableMeson.sol


pragma solidity 0.8.16;


contract UpgradableMeson is UUPSUpgradeable, MesonManager {
  function initialize(address owner, address premiumManager) external initializer {
    _transferOwnership(owner);
    _transferPremiumManager(premiumManager);
  }

  function _authorizeUpgrade(address) internal override onlyOwner {}
}


// File contracts/ProxyToMeson.sol


pragma solidity 0.8.16;


contract ProxyToMeson is ERC1967Proxy {
  bytes4 private constant INITIALIZE_SELECTOR = bytes4(keccak256("initialize(address,address)"));

  constructor(address premiumManager) ERC1967Proxy(_deployImpl(), _encodeData(msg.sender, premiumManager)) {}

  function _deployImpl() private returns (address) {
    UpgradableMeson _impl = new UpgradableMeson();
    return address(_impl);
  }

  function _encodeData(address owner, address premiumManager) private pure returns (bytes memory) {
    return abi.encodeWithSelector(INITIALIZE_SELECTOR, owner, premiumManager);
  }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "evmVersion": "istanbul",
  "metadata": {
    "bytecodeHash": "none"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"premiumManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b506040516154ba3803806154ba83398101604081905261002f91610370565b610037610094565b604080513360248201526001600160a01b0384166044808301919091528251808303909101815260649091019091526020810180516001600160e01b031663485cc95560e01b17905261008c828260006100c6565b50505061040c565b6000806040516100a390610363565b604051809103906000f0801580156100bf573d6000803e3d6000fd5b5092915050565b6100cf836100fc565b6000825111806100dc5750805b156100f7576100f5838361013c60201b6100291760201c565b505b505050565b61010581610168565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061016183836040518060600160405280602781526020016154936027913961023a565b9392505050565b61017b8161031860201b6100551760201c565b6101e25760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806102197f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61032760201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102a25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016101d9565b600080856001600160a01b0316856040516102bd91906103bd565b600060405180830381855af49150503d80600081146102f8576040519150601f19603f3d011682016040523d82523d6000602084013e6102fd565b606091505b50909250905061030e82828661032a565b9695505050505050565b6001600160a01b03163b151590565b90565b60608315610339575081610161565b8251156103495782518084602001fd5b8160405162461bcd60e51b81526004016101d991906103d9565b614d568061073d83390190565b60006020828403121561038257600080fd5b81516001600160a01b038116811461016157600080fd5b60005b838110156103b457818101518382015260200161039c565b50506000910152565b600082516103cf818460208701610399565b9190910192915050565b60208152600082518060208401526103f8816040850160208701610399565b601f01601f19169190910160400192915050565b6103228061041b6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102ef602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b09190610281565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f919061029d565b60005b83811015610278578181015183820152602001610260565b50506000910152565b6000825161029381846020870161025d565b9190910192915050565b60208152600082518060208401526102bc81604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000810000a60a06040523060805234801561001457600080fd5b50608051614d0a61004c60003960008181610b4701528181610bdd015281816112070152818161129d01526113980152614d0a6000f3fe6080604052600436106101cd5760003560e01c80638b0a7765116100f7578063d3c7c2c711610095578063f1d2ec1d11610064578063f1d2ec1d1461060c578063f2fde38b1461062c578063ff22f2721461064c578063ff3787191461066c57600080fd5b8063d3c7c2c71461056e578063d3e95ea414610591578063d4f82322146105b1578063eba7fb77146105d157600080fd5b8063be18e8a4116100d1578063be18e8a4146104ee578063c11d9ecb1461050e578063ce7f79b91461052e578063ce9247431461054e57600080fd5b80638b0a7765146104765780638f487dc9146104ae578063b805f321146104ce57600080fd5b80634d11b0f11161016f57806360a2da981161013e57806360a2da98146103795780637fe0282b146103be5780638302ce5a1461040857806389a734c01461042857600080fd5b80634d11b0f1146103035780634f1ef2861461032357806352d1902d1461033657806354d6a2b71461035957600080fd5b806335eff30f116101ab57806335eff30f146102835780633659cfe6146102a357806337b90a4f146102c3578063485cc955146102e357600080fd5b8063051119f5146101d25780631e2a6075146101f45780632335093c14610241575b600080fd5b3480156101de57600080fd5b506101f26101ed3660046144bc565b6106a2565b005b34801561020057600080fd5b5061021461020f3660046144d7565b6108e3565b604080516001600160a01b0394851681529390921660208401521515908201526060015b60405180910390f35b34801561024d57600080fd5b5061027161025c3660046144bc565b60666020526000908152604090205460ff1681565b60405160ff9091168152602001610238565b34801561028f57600080fd5b506101f261029e366004614505565b61095a565b3480156102af57600080fd5b506101f26102be3660046144bc565b610b3d565b3480156102cf57600080fd5b506101f26102de366004614531565b610cda565b3480156102ef57600080fd5b506101f26102fe36600461456c565b610eb0565b34801561030f57600080fd5b506101f261031e3660046145b5565b611034565b6101f2610331366004614696565b6111fd565b34801561034257600080fd5b5061034b61138b565b604051908152602001610238565b34801561036557600080fd5b506101f26103743660046144d7565b611450565b34801561038557600080fd5b5061039961039436600461475a565b6115c3565b604080516001600160a01b03909316835264ffffffffff909116602083015201610238565b3480156103ca57600080fd5b506103f26103d93660046144bc565b60996020526000908152604090205464ffffffffff1681565b60405164ffffffffff9091168152602001610238565b34801561041457600080fd5b506101f261042336600461477d565b611612565b34801561043457600080fd5b5061045e6104433660046147ef565b609a602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610238565b34801561048257600080fd5b5061034b61049136600461480a565b60281b65ff0000000000166000908152609b602052604090205490565b3480156104ba57600080fd5b506101f26104c9366004614531565b6119f4565b3480156104da57600080fd5b506101f26104e93660046144bc565b611cfe565b3480156104fa57600080fd5b506101f2610509366004614825565b611d0f565b34801561051a57600080fd5b506101f261052936600461490b565b612057565b34801561053a57600080fd5b506101f2610549366004614531565b61218c565b34801561055a57600080fd5b506101f26105693660046149cb565b61235a565b34801561057a57600080fd5b506105836125de565b604051610238929190614a2a565b34801561059d57600080fd5b5061034b6105ac36600461456c565b6127d4565b3480156105bd57600080fd5b506101f26105cc366004614ab1565b612857565b3480156105dd57600080fd5b506040517f23290000000000000000000000000000000000000000000000000000000000008152602001610238565b34801561061857600080fd5b506101f261062736600461475a565b6128bc565b34801561063857600080fd5b506101f26106473660046144bc565b612a51565b34801561065857600080fd5b506101f26106673660046144bc565b612ab5565b34801561067857600080fd5b5061045e61068736600461480a565b6065602052600090815260409020546001600160a01b031681565b3360008181526099602052604081205464ffffffffff16908190036107345760405162461bcd60e51b815260206004820152602360248201527f546865207369676e657220646f6573206e6f742072656769737465722061207060448201527f6f6f6c000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b64ffffffffff81166000908152609a60205260409020546001600160a01b038381169116146107cb5760405162461bcd60e51b815260206004820152602160248201527f4e6565642074686520706f6f6c206f776e657220617320746865207369676e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161072b565b6001600160a01b03831660009081526099602052604090205464ffffffffff8281169116146108625760405162461bcd60e51b815260206004820152602c60248201527f41646472206973206e6f7420617574686f72697a656420666f7220746865207360448201527f69676e6572277320706f6f6c0000000000000000000000000000000000000000606482015260840161072b565b6001600160a01b03831660008181526099602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000169055905191825264ffffffffff8316917f475b83c893df40ee19fd0783cf26478cdb58478dff65bb62560e1e7c36e0f22f91015b60405180910390a2505050565b600081815260ce60205260408120546001600160a01b03602882901c16919078ffffffffffffffffffffffffffffffffffffffffffffffffff16801515908361092f5760009250610952565b64ffffffffff81166000908152609a60205260409020546001600160a01b031692505b509193909250565b600082815260ce602052604090205478ffffffffffffffffffffffffffffffffffffffffffffffffff16600181116109d45760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072b565b8064ffffffffff1615610a295760405162461bcd60e51b815260206004820152601b60248201527f5377617020626f6e64656420746f20616e6f7468657220706f6f6c0000000000604482015260640161072b565b3360009081526099602052604090205464ffffffffff838116911614610ab75760405162461bcd60e51b815260206004820152603860248201527f5369676e65722073686f756c6420626520616e20617574686f72697a6564206160448201527f646472657373206f662074686520676976656e20706f6f6c0000000000000000606482015260840161072b565b600083815260ce602052604080822080547fffffffffffffff000000000000000000000000000000000000000000000000001664ffffffffff861678ffffffffffffffffffffffffffffffffffffffffffffffffff8616171790555184917f60a99b51ae498c44acbbe11031aed2a06a32be66d2122e6e2a7a16c087865cc991a2505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bdb5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161072b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c367f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610cb25760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161072b565b610cbb81612ce9565b60408051600080825260208201909252610cd791839190612d44565b50565b60008211610d2a5760405162461bcd60e51b815260206004820152601760248201527f416d6f756e74206d75737420626520706f736974697665000000000000000000604482015260640161072b565b8064ffffffffff8116600003610d825760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420757365203020617320706f6f6c20696e646578000000000000604482015260640161072b565b3360009081526099602052604090205464ffffffffff828116911614610e105760405162461bcd60e51b815260206004820152602860248201527f4e65656420616e20617574686f72697a6564206164647265737320617320746860448201527f65207369676e6572000000000000000000000000000000000000000000000000606482015260840161072b565b65ffffffffffff82166000908152609b602052604081208054859290610e37908490614b0a565b909155505060ff602883901c16600081815260656020526040902054610e68906001600160a01b0316338684612f02565b8265ffffffffffff167f7d7d1df74ef3a6434d8d63dc0a25d13d5fa94dbe738c38a3cce26e6f892e2a7685604051610ea291815260200190565b60405180910390a250505050565b600054610100900460ff1615808015610ed05750600054600160ff909116105b80610eea5750303b158015610eea575060005460ff166001145b610f5c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161072b565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610fba57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610fc383613195565b610fcc82613256565b801561102f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600086815260ce602052604090205478ffffffffffffffffffffffffffffffffffffffffffffffffff16600181116110ae5760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072b565b6110ba610e1042614b0a565b603088901c64ffffffffff16101561110557600087815260ce6020526040902080547fffffffffffffff0000000000000000000000000000000000000000000000000016905561113d565b600087815260ce6020526040902080547fffffffffffffff000000000000000000000000000000000000000000000000001660011790555b6111588784888888602887901c6001600160a01b031661333d565b868183156111aa5764ffffffffff818116602884901b65ff000000000016176000908152609b60205260408120805460d08d901c939093169290919061119f908490614b0a565b909155506111f29050565b60ff821660009081526065602090815260408083205464ffffffffff8581168552609a9093529220546111f2926001600160a01b039081169291169060d08d901c1685613711565b505050505050505050565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361129b5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161072b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112f67f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b0316146113725760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161072b565b61137b82612ce9565b61138782826001612d44565b5050565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461142b5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161072b565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b600081815260ce602052604090205478ffffffffffffffffffffffffffffffffffffffffffffffffff16600181116114ca5760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072b565b42603083901c64ffffffffff16106115245760405162461bcd60e51b815260206004820152601460248201527f53776170206973207374696c6c206c6f636b6564000000000000000000000000604482015260640161072b565b600082815260ce6020908152604080832080547fffffffffffffff0000000000000000000000000000000000000000000000000016905560ff8516835260659091529020548290611593906001600160a01b0390811690602885901c1664ffffffffff60d085901c1684613711565b60405183907ff6b6b4f7a13f02512c1b3aa8dcc4a07d7775a6a4becbd439efcbd37c5408e67f90600090a2505050565b60008060006115d285856138f0565b6000908152610101602090815260408083205464ffffffffff8082168552609a9093529220546001600160a01b03169760289290921c1695509350505050565b84600161161f8260f81c90565b60ff161461166f5760405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420656e636f64696e672076657273696f6e000000000000604482015260640161072b565b8561232961167d8260081c90565b61ffff16146116ce5760405162461bcd60e51b815260206004820152601760248201527f53776170206e6f7420666f72207468697320636861696e000000000000000000604482015260640161072b565b600087815260ce602052604090205478ffffffffffffffffffffffffffffffffffffffffffffffffff16156117455760405162461bcd60e51b815260206004820152601360248201527f5377617020616c72656164792065786973747300000000000000000000000000604482015260640161072b565b64ffffffffff60d088901c1664174876e8008111156117cc5760405162461bcd60e51b815260206004820152603760248201527f466f7220736563757269747920726561736f6e2c20616d6f756e742063616e6e60448201527f6f742062652067726561746572207468616e203130306b000000000000000000606482015260840161072b565b60006117e34264ffffffffff60308c901c16614b1d565b9050610e1081116118365760405162461bcd60e51b815260206004820152601360248201527f45787069726520747320746f6f206561726c7900000000000000000000000000604482015260640161072b565b611c2081106118875760405162461bcd60e51b815260206004820152601260248201527f45787069726520747320746f6f206c6174650000000000000000000000000000604482015260640161072b565b8464ffffffffff811615611923573360009081526099602052604090205464ffffffffff8281169116146119235760405162461bcd60e51b815260206004820152603860248201527f5369676e65722073686f756c6420626520616e20617574686f72697a6564206160448201527f646472657373206f662074686520676976656e20706f6f6c0000000000000000606482015260840161072b565b6001600160a01b03602887901c1661193e8b8b8b8b85613951565b60008b815260ce6020526040812080547fffffffffffffff000000000000000000000000000000000000000000000000001678ffffffffffffffffffffffffffffffffffffffffffffffffff8a161790558b60ff81166000908152606560205260409020549091506119bb906001600160a01b0316838784612f02565b6040518c907f5ce4019f772fda6cb703b26bce3ec3006eb36b73f1d3a0eb441213317d9f5e9d90600090a2505050505050505050505050565b60008211611a445760405162461bcd60e51b815260206004820152601760248201527f416d6f756e74206d75737420626520706f736974697665000000000000000000604482015260640161072b565b338164ffffffffff8116600003611a9d5760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420757365203020617320706f6f6c20696e646578000000000000604482015260640161072b565b64ffffffffff81166000908152609a60205260409020546001600160a01b031615611b0a5760405162461bcd60e51b815260206004820152601d60248201527f506f6f6c20696e64657820616c72656164792072656769737465726564000000604482015260640161072b565b6001600160a01b03821660009081526099602052604090205464ffffffffff1615611b9d5760405162461bcd60e51b815260206004820152602160248201527f5369676e6572206164647265737320616c72656164792072656769737465726560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161072b565b64ffffffffff81166000818152609a6020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03881690811790915583526099825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000001690941790935565ffffffffffff86168252609b90529081208054869290611c3f908490614b0a565b909155505060ff602884901c16600081815260656020526040902054611c70906001600160a01b0316848784612f02565b6040516001600160a01b038416815264ffffffffff8316907fb8d9c35a714d4e29eaf036b9bf8183a093c5573ac809453b4e8434e25c9126d29060200160405180910390a28365ffffffffffff167f7d7d1df74ef3a6434d8d63dc0a25d13d5fa94dbe738c38a3cce26e6f892e2a7686604051611cef91815260200190565b60405180910390a25050505050565b611d06613c83565b610cd781613256565b846001611d1c8260f81c90565b60ff1614611d6c5760405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420656e636f64696e672076657273696f6e000000000000604482015260640161072b565b85612329611d7a8260201c90565b61ffff1614611dcb5760405162461bcd60e51b815260206004820152601760248201527f53776170206e6f7420666f72207468697320636861696e000000000000000000604482015260640161072b565b6000611dd788856138f0565b6000818152610101602052604090205490915069ffffffffffffffffffff1615611e435760405162461bcd60e51b815260206004820152601360248201527f5377617020616c72656164792065786973747300000000000000000000000000604482015260640161072b565b611e508888888888613951565b3360009081526099602052604081205464ffffffffff1690819003611edd5760405162461bcd60e51b815260206004820152602f60248201527f43616c6c6572206e6f7420726567697374657265642e2043616c6c206465706f60448201527f736974416e6452656769737465722e0000000000000000000000000000000000606482015260840161072b565b6000611eeb6104b042614b0a565b9050611f0461012c64ffffffffff60308d901c16614b1d565b8110611f785760405162461bcd60e51b815260206004820152602560248201527f43616e6e6f74206c6f636b20626563617573652065787069726554732069732060448201527f736f6f6e2e000000000000000000000000000000000000000000000000000000606482015260840161072b565b64ffffffffff82811660108c901b65ff0000000000161790611fa79060588d901c81169060d08e901c16614b1d565b65ffffffffffff82166000908152609b602052604081208054909190611fce908490614b1d565b90915550506000848152610101602052604080822080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001664ffffffffff8716602887901b69ffffffffff00000000001617179055518c917fbfb879c34323c5601fafe832c3a8a1e31e12c288695838726ddeada86034edb491a25050505050505050505050565b610134546001600160a01b031633146120b25760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604482015260640161072b565b80518251146121295760405162461bcd60e51b815260206004820152602e60248201527f546f6b656e7320616e6420696e64657865732073686f756c642068617665207460448201527f68652073616d65206c656e677468000000000000000000000000000000000000606482015260840161072b565b60005b82518160ff16101561102f5761217a838260ff168151811061215057612150614b30565b6020026020010151838360ff168151811061216d5761216d614b30565b6020026020010151613d06565b8061218481614b5f565b91505061212c565b600082116121dc5760405162461bcd60e51b815260206004820152601760248201527f416d6f756e74206d75737420626520706f736974697665000000000000000000604482015260640161072b565b8064ffffffffff81166000036122345760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420757365203020617320706f6f6c20696e646578000000000000604482015260640161072b565b64ffffffffff81166000908152609a60205260409020546001600160a01b031633146122c85760405162461bcd60e51b815260206004820152602160248201527f4e6565642074686520706f6f6c206f776e657220617320746865207369676e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161072b565b65ffffffffffff82166000908152609b6020526040812080548592906122ef908490614b1d565b909155505060ff602883901c16600081815260656020526040902054612320906001600160a01b0316338684613711565b8265ffffffffffff167f34c3d1c46f89307d63d8818fcc5c2a9c07a5f7a01ea4319bfba1899f40c6f40085604051610ea291815260200190565b79400000000000000000000000000000000000000000000000000086161580159061238757612387613c83565b600061239388856138f0565b6000818152610101602052604081205491925069ffffffffffffffffffff909116908190036124045760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072b565b6001600160a01b03841661245a5760405162461bcd60e51b815260206004820181905260248201527f526563697069656e742063616e6e6f74206265207a65726f2061646472657373604482015260640161072b565b4260308a901c64ffffffffff16116124b45760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f742072656c65617365206265636175736520657870697265640000604482015260640161072b565b6124c289858a8a8a8a61333d565b60008281526101016020526040812080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001690556125018a60181c90565b9050600061252164ffffffffff60588d901c81169060d08e901c16614b1d565b9050846125995760006125338c613f02565b905061253f8183614b1d565b915080609b60006125658f600064ffffffffff1660109190911b65ff0000000000161790565b65ffffffffffff1665ffffffffffff16815260200190815260200160002060008282546125929190614b0a565b9091555050505b6125a68b83898985613f27565b6040518b907ffa628b578e095243f0544bfad9255f49d79d03a5bbf6c85875d05a215e247ad290600090a25050505050505050505050565b6060806000805b60ff8260ff161015612643576000606581612601856001614b7e565b60ff1681526020810191909152604001600020546001600160a01b031614612631578061262d81614b5f565b9150505b8161263b81614b5f565b9250506125e5565b8060ff1667ffffffffffffffff81111561265f5761265f614618565b604051908082528060200260200182016040528015612688578160200160208202803683370190505b5093508060ff1667ffffffffffffffff8111156126a7576126a7614618565b6040519080825280602002602001820160405280156126d0578160200160208202803683370190505b50925060008092505b60ff8360ff1610156127cd5760006065816126f5866001614b7e565b60ff1681526020810191909152604001600020546001600160a01b0316146127bb5760656000612726856001614b7e565b60ff1660ff16815260200190815260200160002060009054906101000a90046001600160a01b0316858260ff168151811061276357612763614b30565b6001600160a01b0390921660209283029190910190910152612786836001614b7e565b848260ff168151811061279b5761279b614b30565b60ff90921660209283029190910190910152806127b781614b5f565b9150505b826127c581614b5f565b9350506126d9565b5050509091565b6001600160a01b0380831660009081526066602090815260408083205493851683526099909152812054909160ff169064ffffffffff16801580612819575060ff8216155b1561282957600092505050612851565b64ffffffffff1660289190911b65ff000000000016176000908152609b602052604090205490505b92915050565b610134546001600160a01b031633146128b25760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604482015260640161072b565b6113878282613d06565b60006128c883836138f0565b6000818152610101602052604081205491925069ffffffffffffffffffff909116908190036129395760405162461bcd60e51b815260206004820152601360248201527f5377617020646f6573206e6f7420657869737400000000000000000000000000604482015260640161072b565b42602882901c64ffffffffff16106129935760405162461bcd60e51b815260206004820152601260248201527f53776170207374696c6c20696e206c6f636b0000000000000000000000000000604482015260640161072b565b64ffffffffff818116601086901b65ff00000000001617906129c290605887901c81169060d088901c16614b1d565b65ffffffffffff82166000908152609b6020526040812080549091906129e9908490614b0a565b90915550506000838152610101602052604080822080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001690555186917fac7d23c4f0137a4cc35b0e4b4bc8061ea6cb65805e87ceb0a77ca0c85814858c91a25050505050565b610134546001600160a01b03163314612aac5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604482015260640161072b565b610cd781613195565b6001600160a01b03811660009081526099602052604090205464ffffffffff1615612b485760405162461bcd60e51b815260206004820152602360248201527f4164647220697320617574686f72697a656420666f7220616e6f74686572207060448201527f6f6f6c0000000000000000000000000000000000000000000000000000000000606482015260840161072b565b3360008181526099602052604081205464ffffffffff1690819003612bd55760405162461bcd60e51b815260206004820152602360248201527f546865207369676e657220646f6573206e6f742072656769737465722061207060448201527f6f6f6c0000000000000000000000000000000000000000000000000000000000606482015260840161072b565b64ffffffffff81166000908152609a60205260409020546001600160a01b03838116911614612c6c5760405162461bcd60e51b815260206004820152602160248201527f4e6565642074686520706f6f6c206f776e657220617320746865207369676e6560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161072b565b6001600160a01b03831660008181526099602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000001664ffffffffff8616908117909155915192835290917fd49cde4f679ccef3d23ff07aae4f6845e1c661e23e9fe6a54da26f0723fb695f91016108d6565b610134546001600160a01b03163314610cd75760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604482015260640161072b565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612d775761102f83613faf565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612def575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612dec91810190614b97565b60015b612e615760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f742055555053000000000000000000000000000000000000606482015260840161072b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612ef65760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c65555549440000000000000000000000000000000000000000000000606482015260840161072b565b5061102f838383614085565b6001600160a01b038416612f585760405162461bcd60e51b815260206004820152601360248201527f546f6b656e206e6f7420737570706f7274656400000000000000000000000000604482015260640161072b565b60008211612fa85760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604482015260640161072b565b6001600160a01b0384163b6130255760405162461bcd60e51b815260206004820152602960248201527f54686520676976656e20746f6b656e2061646472657373206973206e6f74206160448201527f20636f6e74726163740000000000000000000000000000000000000000000000606482015260840161072b565b61302e816140b0565b156130455761304264e8d4a5100083614bb0565b91505b604080516001600160a01b038581166024830152306044830152606480830186905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916130d59190614c11565b6000604051808303816000865af19150503d8060008114613112576040519150601f19603f3d011682016040523d82523d6000602084013e613117565b606091505b50915091508180156131415750805115806131415750808060200190518101906131419190614c2d565b61318d5760405162461bcd60e51b815260206004820152601360248201527f7472616e7366657246726f6d206661696c656400000000000000000000000000604482015260640161072b565b505050505050565b6001600160a01b0381166131eb5760405162461bcd60e51b815260206004820181905260248201527f4e6577206f776e65722063616e6e6f74206265207a65726f2061646472657373604482015260640161072b565b61013480546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8934ce4adea8d9ce0d714d2c22b86790e41b7731c84b926fbbdc1d40ff6533c990600090a35050565b6001600160a01b0381166132d25760405162461bcd60e51b815260206004820152602360248201527f4e6577207072656d69756d206d616e61676572206265207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161072b565b61013580546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f4798f31ad3d0ccde6359edf35fc39b882e4e1cff2968ca749b72074d373db27a90600090a35050565b6001600160a01b0381166133935760405162461bcd60e51b815260206004820152601e60248201527f5369676e65722063616e6e6f7420626520656d70747920616464726573730000604482015260640161072b565b8160ff16601b14806133a857508160ff16601c145b6133f45760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072b565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156134645760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072b565b790800000000000000000000000000000000000000000000000000861615156000600888901c61ffff1660c30361356257816134c0577f1954524f4e205369676e6564204d6573736167653a0a33320a000000000000006134e2565b7f1954524f4e205369676e6564204d6573736167653a0a35330a000000000000005b6040517fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009091166020820152603981018990527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089901b166059820152606d015b60405160208183030381529060405280519060200120905061364a565b81156135cc576040517f19457468657265756d205369676e6564204d6573736167653a0a3532000000006020820152603c81018990527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089901b16605c820152607001613545565b60006135d88960201c90565b61ffff1660c314613609577f743e50106a7f059b52151dd4ba27a5f6c87b925ddfbdcf1c332e800da4b3df9261362b565b7f28cf5b919ed55db2b14d9e8b261a523eafb98bab117d3a8a56e559791415d17c5b9050876014528860005260346000206020528060005260406000209150505b60408051600081526020810180835283905260ff861691810191909152606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561369d573d6000803e3d6000fd5b505050602060405103516001600160a01b0316836001600160a01b0316146137075760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072b565b5050505050505050565b6001600160a01b0384163b61378e5760405162461bcd60e51b815260206004820152602960248201527f54686520676976656e20746f6b656e2061646472657373206973206e6f74206160448201527f20636f6e74726163740000000000000000000000000000000000000000000000606482015260840161072b565b613797816140b0565b156137ae576137ab64e8d4a5100083614bb0565b91505b604080516001600160a01b038581166024830152604480830186905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908816916138389190614c11565b6000604051808303816000865af19150503d8060008114613875576040519150601f19603f3d011682016040523d82523d6000602084013e61387a565b606091505b50915091508180156138a45750805115806138a45750808060200190518101906138a49190614c2d565b61318d5760405162461bcd60e51b815260206004820152600f60248201527f7472616e73666572206661696c65640000000000000000000000000000000000604482015260640161072b565b6000828260405160200161393392919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b60405160208183030381529060405280519060200120905092915050565b6001600160a01b0381166139a75760405162461bcd60e51b815260206004820152601e60248201527f5369676e65722063616e6e6f7420626520656d70747920616464726573730000604482015260640161072b565b8160ff16601b14806139bc57508160ff16601c145b613a085760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072b565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613a785760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072b565b790800000000000000000000000000000000000000000000000000851615156000600887901c61ffff1660c303613b4a5781613ad4577f1954524f4e205369676e6564204d6573736167653a0a33320a00000000000000613af6565b7f1954524f4e205369676e6564204d6573736167653a0a33330a000000000000005b6040517fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009091166020820152603981018890526059015b604051602081830303815290604052805190602001209050613bbd565b8115613b88576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101889052605c01613b2d565b506000868152602080822090527f9862d877599564bcd97c37305a7b0fdbe621d9c2a125026f2ad601f754a75abc8152604090205b60408051600081526020810180835283905260ff861691810191909152606081018790526080810186905260019060a0016020604051602081039080840390855afa158015613c10573d6000803e3d6000fd5b505050602060405103516001600160a01b0316836001600160a01b031614613c7a5760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015260640161072b565b50505050505050565b610135546001600160a01b03163314613d045760405162461bcd60e51b815260206004820152602160248201527f43616c6c6572206973206e6f7420746865207072656d69756d206d616e61676560448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840161072b565b565b8060ff16600003613d595760405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f7420757365203020617320746f6b656e20696e6465780000000000604482015260640161072b565b6001600160a01b038216613daf5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f7420757365207a65726f2061646472657373000000000000000000604482015260640161072b565b6001600160a01b03821660009081526066602052604090205460ff1615613e185760405162461bcd60e51b815260206004820152601b60248201527f546f6b656e20686173206265656e206164646564206265666f72650000000000604482015260640161072b565b60ff81166000908152606560205260409020546001600160a01b031615613e815760405162461bcd60e51b815260206004820152601360248201527f496e64657820686173206265656e207573656400000000000000000000000000604482015260640161072b565b6001600160a01b039091166000818152606660209081526040808320805460ff9096167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090961686179055938252606590529190912080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b6000612710613f1d600a64ffffffffff60d086901c16614bb0565b6128519190614c4a565b7980000000000000000000000000000000000000000000000000008516613f805760ff8416600090815260656020526040902054613f7b906001600160a01b031683858488613f768b60801c90565b6140ca565b613fa8565b60ff8416600090815260656020526040902054613fa8906001600160a01b0316838387613711565b5050505050565b6001600160a01b0381163b61402c5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161072b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61408e83614315565b60008251118061409b5750805b1561102f576140aa8383614355565b50505050565b600060208260ff1611801561285157505060ff9081161090565b6001600160a01b0386163b6141475760405162461bcd60e51b815260206004820152602960248201527f54686520676976656e20746f6b656e2061646472657373206973206e6f74206160448201527f20636f6e74726163740000000000000000000000000000000000000000000000606482015260840161072b565b6001600160a01b0385163b6141c45760405162461bcd60e51b815260206004820152602d60248201527f54686520676976656e20726563697069656e742061646472657373206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161072b565b6141cd826140b0565b156141e4576141e164e8d4a5100084614bb0565b92505b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301526024820185905287169063095ea7b3906044016020604051808303816000875af115801561424c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142709190614c2d565b506040517f3ea1ef2d0000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260248201859052858116604483015267ffffffffffffffff83166064830152861690633ea1ef2d906084016020604051808303816000875af11580156142f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c7a9190614c2d565b61431e81613faf565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6143d45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161072b565b600080846001600160a01b0316846040516143ef9190614c11565b600060405180830381855af49150503d806000811461442a576040519150601f19603f3d011682016040523d82523d6000602084013e61442f565b606091505b50915091506144578282604051806060016040528060278152602001614cd760279139614460565b95945050505050565b6060831561446f575081614499565b82511561447f5782518084602001fd5b8160405162461bcd60e51b815260040161072b9190614c85565b9392505050565b80356001600160a01b03811681146144b757600080fd5b919050565b6000602082840312156144ce57600080fd5b614499826144a0565b6000602082840312156144e957600080fd5b5035919050565b803564ffffffffff811681146144b757600080fd5b6000806040838503121561451857600080fd5b82359150614528602084016144f0565b90509250929050565b6000806040838503121561454457600080fd5b82359150602083013565ffffffffffff8116811461456157600080fd5b809150509250929050565b6000806040838503121561457f57600080fd5b614588836144a0565b9150614528602084016144a0565b803560ff811681146144b757600080fd5b8015158114610cd757600080fd5b60008060008060008060c087890312156145ce57600080fd5b8635955060208701359450604087013593506145ec60608801614596565b92506145fa608088016144a0565b915060a087013561460a816145a7565b809150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561468e5761468e614618565b604052919050565b600080604083850312156146a957600080fd5b6146b2836144a0565b915060208084013567ffffffffffffffff808211156146d057600080fd5b818601915086601f8301126146e457600080fd5b8135818111156146f6576146f6614618565b614726847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614647565b9150808252878482850101111561473c57600080fd5b80848401858401376000848284010152508093505050509250929050565b6000806040838503121561476d57600080fd5b82359150614528602084016144a0565b600080600080600060a0868803121561479557600080fd5b8535945060208601359350604086013592506147b360608701614596565b9150608086013578ffffffffffffffffffffffffffffffffffffffffffffffffff811681146147e157600080fd5b809150509295509295909350565b60006020828403121561480157600080fd5b614499826144f0565b60006020828403121561481c57600080fd5b61449982614596565b600080600080600060a0868803121561483d57600080fd5b85359450602086013593506040860135925061485b60608701614596565b9150614869608087016144a0565b90509295509295909350565b600067ffffffffffffffff82111561488f5761488f614618565b5060051b60200190565b600082601f8301126148aa57600080fd5b813560206148bf6148ba83614875565b614647565b82815260059290921b840181019181810190868411156148de57600080fd5b8286015b84811015614900576148f381614596565b83529183019183016148e2565b509695505050505050565b6000806040838503121561491e57600080fd5b823567ffffffffffffffff8082111561493657600080fd5b818501915085601f83011261494a57600080fd5b8135602061495a6148ba83614875565b82815260059290921b8401810191818101908984111561497957600080fd5b948201945b8386101561499e5761498f866144a0565b8252948201949082019061497e565b965050860135925050808211156149b457600080fd5b506149c185828601614899565b9150509250929050565b60008060008060008060c087890312156149e457600080fd5b863595506020870135945060408701359350614a0260608801614596565b9250614a10608088016144a0565b9150614a1e60a088016144a0565b90509295509295509295565b604080825283519082018190526000906020906060840190828701845b82811015614a6c5781516001600160a01b031684529284019290840190600101614a47565b5050508381038285015284518082528583019183019060005b81811015614aa457835160ff1683529284019291840191600101614a85565b5090979650505050505050565b60008060408385031215614ac457600080fd5b614acd836144a0565b915061452860208401614596565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561285157612851614adb565b8181038181111561285157612851614adb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff821660ff8103614b7557614b75614adb565b60010192915050565b60ff818116838216019081111561285157612851614adb565b600060208284031215614ba957600080fd5b5051919050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614be857614be8614adb565b500290565b60005b83811015614c08578181015183820152602001614bf0565b50506000910152565b60008251614c23818460208701614bed565b9190910192915050565b600060208284031215614c3f57600080fd5b8151614499816145a7565b600082614c80577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6020815260008251806020840152614ca4816040850160208701614bed565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000810000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564000000000000000000000000666d6b8a44d226150ca9058beebafe0e3ac065a2

Deployed Bytecode

0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102ef602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b09190610281565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f919061029d565b60005b83811015610278578181015183820152602001610260565b50506000910152565b6000825161029381846020870161025d565b9190910192915050565b60208152600082518060208401526102bc81604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000810000a

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

000000000000000000000000666d6b8a44d226150ca9058beebafe0e3ac065a2

-----Decoded View---------------
Arg [0] : premiumManager (address): 0x666d6b8a44d226150ca9058bEEbafe0e3aC065A2

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000666d6b8a44d226150ca9058beebafe0e3ac065a2


Deployed ByteCode Sourcemap

107645:570:0:-:0;;;;;;2986:11;:9;:11::i;:::-;107645:570;;2763:11;2410:110;2485:28;2495:17;:15;:17::i;:::-;2485:9;:28::i;:::-;2410:110::o;11340:198::-;11423:12;11454:77;11475:6;11483:4;11454:77;;;;;;;;;;;;;;;;;:20;:77::i;:::-;11447:84;11340:198;-1:-1:-1;;;11340:198:0:o;5945:320::-;6235:19;;;:23;;;5945:320::o;14723:190::-;14893:4;14723:190::o;23326:140::-;23393:12;23424:35;16706:66;17056:54;;;;16977:140;23424:35;23417:42;;23326:140;:::o;1036:895::-;1374:14;1371:1;1368;1355:34;1588:1;1585;1569:14;1566:1;1550:14;1543:5;1530:60;1664:16;1661:1;1658;1643:38;1702:6;1769:66;;;;1884:16;1881:1;1874:27;1769:66;1804:16;1801:1;1794:27;11724:387;11865:12;6235:19;;;;11889:69;;;;;;;216:2:1;11889:69:0;;;198:21:1;255:2;235:18;;;228:30;294:34;274:18;;;267:62;365:8;345:18;;;338:36;391:19;;11889:69:0;;;;;;;;;11970:12;11984:23;12011:6;:19;;12031:4;12011:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11969:67;;;;12053:51;12070:7;12079:10;12091:12;12053:16;:51::i;:::-;12046:58;11724:387;-1:-1:-1;;;;;;11724:387:0:o;12331:742::-;12477:12;12505:7;12501:566;;;-1:-1:-1;12535:10:0;12528:17;;12501:566;12646:17;;:21;12642:415;;12890:10;12884:17;12950:15;12937:10;12933:2;12929:19;12922:44;12642:415;13029:12;13022:20;;;;;;;;;;;:::i;421:250:1:-;506:1;516:113;530:6;527:1;524:13;516:113;;;606:11;;;600:18;587:11;;;580:39;552:2;545:10;516:113;;;-1:-1:-1;;663:1:1;645:16;;638:27;421:250::o;676:287::-;805:3;843:6;837:13;859:66;918:6;913:3;906:4;898:6;894:17;859:66;:::i;:::-;941:16;;;;;676:287;-1:-1:-1;;676:287:1:o;968:455::-;1117:2;1106:9;1099:21;1080:4;1149:6;1143:13;1192:6;1187:2;1176:9;1172:18;1165:34;1208:79;1280:6;1275:2;1264:9;1260:18;1255:2;1247:6;1243:15;1208:79;:::i;:::-;1339:2;1327:15;1344:66;1323:88;1308:104;;;;1414:2;1304:113;;968:455;-1:-1:-1;;968:455:1:o

Metadata Hash

none
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.