Contract 0xbec70f2e023c823442cf2d21b95ea21ff7575267

Contract Overview

Balance:
0 ETH
Txn Hash Method
Block
From
To
Value
0xe3fdb32b61f539a9b8b443f96a9b12b8d0b197204b75982ba8d5ea1b810d22aeSet Bridge87634022023-05-01 15:27:52301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007655191827.50000025
0xbb9be63e98af3b7ea42b3471c066babd5fd65058f92287ce800db7a327c7bc5bSet Bridge87633992023-05-01 15:27:46301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007652860047.50000025
0xcc29336d3f6ea54bc78024608832e1cf32070ce932b7c72fc6328aad5bf9e2bdSet Bridge87633952023-05-01 15:27:38301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007652860047.50000025
0xb952bc58adf6f34cc1cbd97eca5fa73e4a4d291e77a0cbfa95459ed561978928Set Bridge87633922023-05-01 15:27:32301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007652860047.50000025
0x13b0e1c956c40742c6dc027a42e8c119ae0422da1ebc754053298a63745e6510Set Bridge87633882023-05-01 15:27:24301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007652860047.50000025
0x46044a6159b4335035c95649989e921ae2f390a63c55373dfdc10a2491c2b502Set Bridge87633852023-05-01 15:27:18301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007652860047.50000025
0x3aaae6054427376f368790de3e22bdea4409bcc791d72f27d68ac5e9bb295af0Set Bridge87633812023-05-01 15:27:10301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007707808687.50000025
0x84d4ff513e57b2539a176953c4eb05b16458d28cac7e879adcb0d003a3703c0bSet Bridge87633782023-05-01 15:27:04301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007707808687.50000025
0x2a9c6528fb0c66b7de0b31438ba3a0439bd3f1914ec8137fbc25b8f1e83ea13bSet Bridge87633752023-05-01 15:26:58301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.000773826557.50000025
0xe24cdd898543810e4c1de6e67f9901118e9c040fbe0d5fc09af05e66263ddb7bSet Bridge87633712023-05-01 15:26:50301 days 22 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0007672558847.50000025
0x0761435dba2ced8ef5d1226b9ccdb70cafae9f64fa46998dc21c31e01a413a37Set Gas Amount87609462023-05-01 14:06:00301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00215389223837.50000125
0x489e2bbd3622e0debb75622cbde3e3acd36f8bccba0f46cdf4df56c0a6db4e3bSet Gas Amount87609422023-05-01 14:05:52301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00215389223837.50000125
0xeb58b199dd7e7457c484bd723e2b62b6f9a797a6675fa712b760d4162a9e4ff8Set Gas Amount87609392023-05-01 14:05:46301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00210973521437.50000125
0x3d691f5b14887011b0f96609f0c6b911e526c1ee47fdfda72a59eec4c75e2079Set Gas Amount87609352023-05-01 14:05:38301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00210973521437.50000125
0x798b7f32194a4978c4643baa8648f7f5bf9757f256172734683838cf801b759eSet Gas Amount87609322023-05-01 14:05:32301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00207019903437.50000125
0x990a48553d912a80063b149d55305adb90ea61dc1ba135b3981545ce74d76db8Set Gas Amount87609292023-05-01 14:05:26301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00207109140637.50000125
0xdb27f333cfdd89dd94d7bc9823f678aa3ab8b18af335aea1cd33ad8b375f27caSet Gas Amount87609252023-05-01 14:05:18301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00203618583837.50000125
0x8e2b94627008c7d9f3443b33efaf1daa32a67d9580db09b21571d3e68f1a2ce9Set Gas Amount87609222023-05-01 14:05:12301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00200580076137.50000125
0x7be57d777ef9b39f1039488908d7123f602346afa2c4b52c0f066a607d6f3c27Set Gas Amount87609182023-05-01 14:05:04301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.00200438043137.50000125
0xc3abcb5a6c709dcd4bc409a228dd41fdb283b3e8e636bb0e4c5562addfdde5a8Set Gas Amount87609152023-05-01 14:04:58301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0006047407147.50000025
0x611d36921948d2b17ea75a0d90244c0ef0ccf0b5e12c37142fb1dd1d70e6e7c6Set Gas Amount87609112023-05-01 14:04:50301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0006047407147.50000025
0x375e367ca884777299b3b23be98933bf4fc344f0dd29db360c7ebed757be28f0Set Gas Amount87609082023-05-01 14:04:44301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0005771368447.50000025
0xb039ae43a46dac2459fbc08f20bb31d82d2a52d4b7398f5424d6d7cc1af8436fSet Gas Amount87609052023-05-01 14:04:38301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0005758705827.50000025
0x1e4893373d4941b123551e1b1ad9912cb87cc1948f0ff5ec368fd10479f04a01Set Gas Amount87609012023-05-01 14:04:30301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0005698777.50000025
0xc2ccbdd54e9e119970b6929d05096499c53fd257023bf362480a066799cfd658Set Gas Amount87608982023-05-01 14:04:24301 days 23 hrs ago0x256fdf96349a412a97bc9b0d21519ec19232816f IN 0xbec70f2e023c823442cf2d21b95ea21ff75752670 ETH0.0005865991547.50000025
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x04af2efde10896e5d815ea7e4f135e1f9fa5af53ede43969fab84df3955bf77d212856332024-02-15 12:15:3412 days 1 hr ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000438344059864876 ETH
0x04af2efde10896e5d815ea7e4f135e1f9fa5af53ede43969fab84df3955bf77d212856332024-02-15 12:15:3412 days 1 hr ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000438344059864876 ETH
0x00602c813224e0b25e165d91aeb760a3ee905f0562592b9eb0ac415d534b73bc212841542024-02-15 11:26:1612 days 2 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000004171704036027 ETH
0x00602c813224e0b25e165d91aeb760a3ee905f0562592b9eb0ac415d534b73bc212841542024-02-15 11:26:1612 days 2 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000004171704036027 ETH
0x676cd0caa860b829c5d3ed12b20f954f91c5f6fab094f4d7a16dbe2703aeee5b212788092024-02-15 8:28:0612 days 5 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.00000386208708819 ETH
0x676cd0caa860b829c5d3ed12b20f954f91c5f6fab094f4d7a16dbe2703aeee5b212788092024-02-15 8:28:0612 days 5 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.00000386208708819 ETH
0x248341008e29f7856609df81452eefd1e9762ea82b77b0a6f64366ff252ef031212787922024-02-15 8:27:3212 days 5 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000438344059864876 ETH
0x248341008e29f7856609df81452eefd1e9762ea82b77b0a6f64366ff252ef031212787922024-02-15 8:27:3212 days 5 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000438344059864876 ETH
0xf0ab6dfa8b0e025ba7e7520785933ceb477ab2b26284a0919a4871cfc7e2834e212787712024-02-15 8:26:5012 days 5 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000004171704036027 ETH
0xf0ab6dfa8b0e025ba7e7520785933ceb477ab2b26284a0919a4871cfc7e2834e212787712024-02-15 8:26:5012 days 5 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000004171704036027 ETH
0x95e2fa672a28cb0631ef93e55b8751c9254be054352e0133eae413658392519f212787482024-02-15 8:26:0412 days 5 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000699440190410745 ETH
0x95e2fa672a28cb0631ef93e55b8751c9254be054352e0133eae413658392519f212787482024-02-15 8:26:0412 days 5 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000699440190410745 ETH
0xaedd64b7624796567ca6fae1847832a3cffacc12e481e8475c20eb0fb6451dbc212681122024-02-15 2:31:3212 days 11 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000699440190410745 ETH
0xaedd64b7624796567ca6fae1847832a3cffacc12e481e8475c20eb0fb6451dbc212681122024-02-15 2:31:3212 days 11 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000699440190410745 ETH
0x6645dcbe5e1d1bcd801a2181bdff00db83e34135e968db8be9d60a4295764d05212677292024-02-15 2:18:4612 days 11 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000004172549421662 ETH
0x6645dcbe5e1d1bcd801a2181bdff00db83e34135e968db8be9d60a4295764d05212677292024-02-15 2:18:4612 days 11 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000004172549421662 ETH
0x3ed8a44da2775089b31bbf1c571ff1c4f1812f7ea3f6f174c16a229ceca796cb212615822024-02-14 22:53:5212 days 14 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000004180110323204 ETH
0x3ed8a44da2775089b31bbf1c571ff1c4f1812f7ea3f6f174c16a229ceca796cb212615822024-02-14 22:53:5212 days 14 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000004180110323204 ETH
0x87cd30be067449a8d13c6f4db300ed5cc1e3c6c7198452d836deb1e89e9656a9212479762024-02-14 15:20:2012 days 22 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000699440190410745 ETH
0x87cd30be067449a8d13c6f4db300ed5cc1e3c6c7198452d836deb1e89e9656a9212479762024-02-14 15:20:2012 days 22 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000699440190410745 ETH
0xdf4456634c371061361ae0f44a38c46ee461aeb0f671f751d8b2e5ae896b4982212455572024-02-14 13:59:4212 days 23 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000004181041627936 ETH
0xdf4456634c371061361ae0f44a38c46ee461aeb0f671f751d8b2e5ae896b4982212455572024-02-14 13:59:4212 days 23 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000004181041627936 ETH
0x31f4795842a70435f12f3f9ba719b31821555af6c3b0ab7030caf6e5b0879a5d212453932024-02-14 13:54:1412 days 23 hrs ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000438344059864876 ETH
0x31f4795842a70435f12f3f9ba719b31821555af6c3b0ab7030caf6e5b0879a5d212453932024-02-14 13:54:1412 days 23 hrs ago 0x9731f8a3b2a9ee5e017483e6b4b62a9ac1af532d0xbec70f2e023c823442cf2d21b95ea21ff75752670.000438344059864876 ETH
0xc580e854b6760bcdfa3aaffbf2a238469a1a17f272d16a60ce60ab6d271d75be212452512024-02-14 13:49:3013 days ago 0xbec70f2e023c823442cf2d21b95ea21ff7575267 0xae92d5ad7583ad66e49a0c67bad18f6ba52dddc10.000004181041627936 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Bridge

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 800 runs

Other Settings:
default evmVersion, MIT license
File 1 of 15 : AccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(account),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * May emit a {RoleGranted} event.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 2 of 15 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

File 3 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

File 4 of 15 : Context.sol
// SPDX-License-Identifier: MIT
// 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 5 of 15 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

File 6 of 15 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 7 of 15 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 8 of 15 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

File 9 of 15 : SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 10 of 15 : Bridge.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import "@openzeppelin/contracts/access/AccessControl.sol";

import "./interfaces/IAssetRouter.sol";
import "./interfaces/ILayerZeroReceiver.sol";
import "./interfaces/ILayerZeroEndpoint.sol";
import "./interfaces/ILayerZeroUserApplicationConfig.sol";
import "./interfaces/IBridge.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "@openzeppelin/contracts/utils/math/SafeMath.sol";

// import "hardhat/console.sol";

contract Bridge is AccessControl, IBridge {
    using SafeMath for uint256;

    bytes32 public constant ROUTER_ROLE = keccak256("ROUTER_ROLE");

    ILayerZeroEndpoint public immutable layerZeroEndpoint;
    mapping(uint16 => bytes) public bridgeLookup;
    mapping(uint16 => mapping(IAssetRouter.MESSAGE_TYPE => uint256)) public gasLookup;
    IAssetRouter public router;
    bool public useLayerZeroToken;

    mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;

    /// @notice received parameters per chain per action id for both swap or vouchers
    mapping(uint16 => mapping(bytes32 => IAssetRouter.SwapMessage)) private receivedSwapMessages;
    mapping(uint16 => mapping(bytes32 => IAssetRouter.LiquidityMessage)) private receivedLiquidityMessages;

    event MessageDispatched(
        uint16 indexed chainId,
        IAssetRouter.MESSAGE_TYPE indexed type_,
        address indexed refundAddress,
        bytes payload
    );

    event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload);
    event SwapMessageReceived(IAssetRouter.SwapMessage _message);
    event LiquidityMessageReceived(IAssetRouter.LiquidityMessage _message);

    error InsuficientFee(uint256);
    error NotLayerZero();
    error InsufficientAccess();
    error BridgeMismatch();
    error SliceOverflow();
    error SliceBoundsError();

    constructor(address _layerZeroEndpoint, address _router) {
        layerZeroEndpoint = ILayerZeroEndpoint(_layerZeroEndpoint);
        router = IAssetRouter(_router);
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _setupRole(ROUTER_ROLE, msg.sender);
    }

    function dispatchMessage(
        uint16 _chainId,
        IAssetRouter.MESSAGE_TYPE _type,
        address payable _refundAddress,
        bytes memory _payload
    ) external payable override onlyRole(ROUTER_ROLE) {
        uint16 version = 1;
        bytes memory adapterParams = abi.encodePacked(version, gasLookup[_chainId][_type]);
        (uint256 estimatedFee, ) = layerZeroEndpoint.estimateFees(
            _chainId,
            address(this),
            _payload,
            false,
            adapterParams
        );
        if (estimatedFee > msg.value) {
            revert InsuficientFee(estimatedFee);
        }

        layerZeroEndpoint.send{ value: msg.value }(
            _chainId,
            bridgeLookup[_chainId],
            _payload,
            _refundAddress,
            address(this),
            adapterParams
        );
        emit MessageDispatched(_chainId, _type, _refundAddress, _payload);
    }

    function lzReceive(
        uint16 srcChainId_,
        bytes memory srcAddressBytes_,
        uint64 nonce_,
        bytes memory payload_
    ) external override {
        if (msg.sender != address(layerZeroEndpoint)) revert NotLayerZero();
        try this.nonBlockingReceive(srcChainId_, srcAddressBytes_, payload_) {} catch {
            failedMessages[srcChainId_][srcAddressBytes_][nonce_] = keccak256(payload_);
            emit MessageFailed(srcChainId_, srcAddressBytes_, nonce_, payload_);
        }
    }

    // use this method for testing
    // function lzReceive(
    //     uint16 srcChainId_,
    //     bytes memory srcAddressBytes_,
    //     uint64 nonce_,
    //     bytes memory payload_
    // ) external override {
    //     nonBlockingReceive(srcChainId_, srcAddressBytes_, payload_);
    // }

    function nonBlockingReceive(uint16 srcChainId_, bytes memory srcAddressBytes_, bytes memory payload_) public {
        // TODO remove this for testing
        if (msg.sender != address(this) && !hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert InsufficientAccess();
        if (
            srcAddressBytes_.length != bridgeLookup[srcChainId_].length ||
            keccak256(srcAddressBytes_) != keccak256(bridgeLookup[srcChainId_])
        ) {
            revert BridgeMismatch();
        }
        handleReceive(srcChainId_, payload_);
    }

    function handleReceive(uint16 _srcChainId, bytes memory _payload) internal {
        uint8 functionType;
        assembly ("memory-safe") {
            functionType := mload(add(_payload, 1))
        }
        if (functionType == 1) {
            IAssetRouter.SwapMessage memory swapMessage = decodeSwapMessage(_payload);
            swapMessage.srcChainId = _srcChainId;

            receivedSwapMessages[_srcChainId][swapMessage.id] = swapMessage;

            router.swapRemote(
                swapMessage.srcPoolId,
                swapMessage.dstPoolId,
                _srcChainId,
                swapMessage.receiver,
                swapMessage.amount,
                swapMessage.fee,
                swapMessage.vouchers,
                swapMessage.optimalDstBandwidth
            );
            emit SwapMessageReceived(swapMessage);
        } else if (functionType == 2) {
            IAssetRouter.LiquidityMessage memory liquidityMessage = decodeLiquidityMessage(_payload);

            receivedLiquidityMessages[_srcChainId][liquidityMessage.id] = liquidityMessage;
            router.receiveVouchers(
                _srcChainId,
                liquidityMessage.srcPoolId,
                liquidityMessage.dstPoolId,
                liquidityMessage.vouchers,
                liquidityMessage.optimalDstBandwidth,
                false
            );
            emit LiquidityMessageReceived(liquidityMessage);
        }
    }

    function decodeSwapMessage(
        bytes memory _payload
    ) private pure returns (IAssetRouter.SwapMessage memory swapMessage) {
        uint16 scrPoolId;
        uint16 dstPoolId;
        address receiver;
        uint256 amount;
        uint256 fee;
        uint256 vouchers;
        uint256 optimalDstBandwidth;
        bytes32 id;
        swapMessage.payload = slice(_payload, 185, _payload.length - 185);

        assembly ("memory-safe") {
            _payload := add(_payload, 1)

            scrPoolId := mload(add(_payload, 2))
            _payload := add(_payload, 2)

            dstPoolId := mload(add(_payload, 2))
            _payload := add(_payload, 2)

            receiver := mload(add(_payload, 20))
            _payload := add(_payload, 20)

            amount := mload(add(_payload, 32))
            _payload := add(_payload, 32)

            fee := mload(add(_payload, 32))
            _payload := add(_payload, 32)

            vouchers := mload(add(_payload, 32))
            _payload := add(_payload, 32)

            optimalDstBandwidth := mload(add(_payload, 32))
            _payload := add(_payload, 32)

            id := mload(add(_payload, 32))
            _payload := add(_payload, 32)
        }
        swapMessage.srcPoolId = scrPoolId;
        swapMessage.dstPoolId = dstPoolId;
        swapMessage.receiver = receiver;
        swapMessage.amount = amount;
        swapMessage.fee = fee;
        swapMessage.vouchers = vouchers;
        swapMessage.optimalDstBandwidth = optimalDstBandwidth;
        swapMessage.id = id;
    }

    function decodeLiquidityMessage(
        bytes memory _payload
    ) private pure returns (IAssetRouter.LiquidityMessage memory liquidityMessage) {
        uint16 scrPoolId;
        uint16 dstPoolId;
        uint256 vouchers;
        uint256 optimalDstBandwidth;
        bytes32 id;

        assembly ("memory-safe") {
            _payload := add(_payload, 1)

            scrPoolId := mload(add(_payload, 2))
            _payload := add(_payload, 2)

            dstPoolId := mload(add(_payload, 2))
            _payload := add(_payload, 2)

            vouchers := mload(add(_payload, 32))
            _payload := add(_payload, 32)

            optimalDstBandwidth := mload(add(_payload, 32))
            _payload := add(_payload, 32)

            id := mload(add(_payload, 32))
            _payload := add(_payload, 32)
        }
        liquidityMessage.srcPoolId = scrPoolId;
        liquidityMessage.dstPoolId = dstPoolId;
        liquidityMessage.vouchers = vouchers;
        liquidityMessage.optimalDstBandwidth = optimalDstBandwidth;
        liquidityMessage.id = id;
    }

    function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {
        if (_length + 31 < _length) revert SliceOverflow();
        if (_bytes.length < _start + _length) revert SliceBoundsError();

        bytes memory tempBytes;

        // Check length is 0. `iszero` return 1 for `true` and 0 for `false`.
        assembly ("memory-safe") {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // Calculate length mod 32 to handle slices that are not a multiple of 32 in size.
                let lengthmod := and(_length, 31)

                // tempBytes will have the following format in memory: <length><data>
                // When copying data we will offset the start forward to avoid allocating additional memory
                // Therefore part of the length area will be written, but this will be overwritten later anyways.
                // In case no offset is require, the start is set to the data region (0x20 from the tempBytes)
                // mc will be used to keep track where to copy the data to.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // Same logic as for mc is applied and additionally the start offset specified for the method is added
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    // increase `mc` and `cc` to read the next word from memory
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // Copy the data from source (cc location) to the slice data (mc location)
                    mstore(mc, mload(cc))
                }

                // Store the length of the slice. This will overwrite any partial data that
                // was copied when having slices that are not a multiple of 32.
                mstore(tempBytes, _length)

                // update free-memory pointer
                // allocating the array padded to 32 bytes like the compiler does now
                // To set the used memory as a multiple of 32, add 31 to the actual memory usage (mc)
                // and remove the modulo 32 (the `and` with `not(31)`)
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            // if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
                // zero out the 32 bytes slice we are about to return
                // we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                // update free-memory pointer
                // tempBytes uses 32 bytes in memory (even when empty) for the length.
                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    /**
     * @notice  Returns the fee for a message sent onchain
     * @dev The parameters within this function are mock parameters as L0 fee calculation is based on params length and not the actual parameters
     *      That is why we are using address(this) as mock address
     * @param _chainId to what chain we want to estimate
     * @param _type what type of message we want to estimate
     * @param _payload the payload we want to send with the message, this is the actual payload we want to send with that type of message
     * @return
     * @return
     */
    function quoteLayerZeroFee(
        uint16 _chainId,
        IAssetRouter.MESSAGE_TYPE _type,
        bytes memory _payload
    ) external view returns (uint256, uint256) {
        bytes memory encodedMessage = "";

        if (_type == IAssetRouter.MESSAGE_TYPE.SWAP) {
            encodedMessage = abi.encodePacked(
                IAssetRouter.MESSAGE_TYPE.SWAP,
                type(uint16).max,
                type(uint16).max,
                address(this),
                type(uint256).max,
                type(uint256).max,
                type(uint256).max,
                type(uint256).max,
                keccak256(abi.encode(address(this), 1, 1, IAssetRouter.MESSAGE_TYPE.SWAP)),
                _payload
            );
        } else if (_type == IAssetRouter.MESSAGE_TYPE.ADD_LIQUIDITY) {
            encodedMessage = abi.encodePacked(
                IAssetRouter.MESSAGE_TYPE.ADD_LIQUIDITY,
                type(uint16).max,
                type(uint16).max,
                type(uint256).max,
                type(uint256).max,
                keccak256(abi.encode(address(this), 1, 1, IAssetRouter.MESSAGE_TYPE.SWAP))
            );
        } else {
            revert("invalid operation");
        }

        uint16 version = 1;
        bytes memory adapterParams = abi.encodePacked(version, gasLookup[_chainId][_type]);
        return
            layerZeroEndpoint.estimateFees(_chainId, address(this), encodedMessage, useLayerZeroToken, adapterParams);
    }

    function nextNonce(uint16 dstChain_) public view override returns (uint256) {
        return layerZeroEndpoint.getOutboundNonce(dstChain_, address(this)) + 1;
    }

    function getReceivedSwaps(
        uint16 srcChain_,
        bytes32 id_
    ) external view override returns (IAssetRouter.SwapMessage memory) {
        return receivedSwapMessages[srcChain_][id_];
    }

    function getReceivedLiquidity(
        uint16 srcChain_,
        bytes32 id_
    ) external view override returns (IAssetRouter.LiquidityMessage memory) {
        return receivedLiquidityMessages[srcChain_][id_];
    }

    function setBridge(uint16 _chainId, bytes calldata _bridgeAddress) external onlyRole(DEFAULT_ADMIN_ROLE) {
        bridgeLookup[_chainId] = abi.encodePacked(_bridgeAddress, address(this));
    }

    function setRouter(IAssetRouter _newRouter) external onlyRole(DEFAULT_ADMIN_ROLE) {
        router = _newRouter;
    }

    function setGasAmount(
        uint16 _chainId,
        IAssetRouter.MESSAGE_TYPE _functionType,
        uint256 _gasAmount
    ) external onlyRole(DEFAULT_ADMIN_ROLE) {
        gasLookup[_chainId][_functionType] = _gasAmount;
    }

    function approveTokenSpender(address token, address spender, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) {
        IERC20(token).approve(spender, amount);
    }

    function setUseLayerZeroToken(bool enable) external onlyRole(DEFAULT_ADMIN_ROLE) {
        useLayerZeroToken = enable;
    }

    function forceResumeReceive(
        uint16 _srcChainId,
        bytes calldata _srcAddress
    ) external override onlyRole(DEFAULT_ADMIN_ROLE) {
        layerZeroEndpoint.forceResumeReceive(_srcChainId, _srcAddress);
    }

    function setConfig(
        uint16 _version,
        uint16 _chainId,
        uint256 _configType,
        bytes calldata _config
    ) external override onlyRole(DEFAULT_ADMIN_ROLE) {
        layerZeroEndpoint.setConfig(_version, _chainId, _configType, _config);
    }

    function setSendVersion(uint16 version) external override onlyRole(DEFAULT_ADMIN_ROLE) {
        layerZeroEndpoint.setSendVersion(version);
    }

    function setReceiveVersion(uint16 version) external override onlyRole(DEFAULT_ADMIN_ROLE) {
        layerZeroEndpoint.setReceiveVersion(version);
    }
}

File 11 of 15 : IAssetRouter.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IAssetRouter {
    //---------------------------------------------------------------------------
    // STRUCTS
    struct ChainPath {
        bool active;
        uint16 srcPoolId;
        uint16 dstChainId;
        uint16 dstPoolId;
        uint16 weight;
        uint256 bandwidth; // local bandwidth
        uint256 actualBandwidth; // local bandwidth
        uint256 kbp; // kbp = Known Bandwidth Proof dst bandwidth
        uint256 actualKbp; // kbp = Known Bandwidth Proof dst bandwidth
        uint256 vouchers;
        uint256 optimalDstBandwidth; // optimal dst bandwidth
        address poolAddress;
    }

    struct SwapParams {
        uint16 srcPoolId;
        uint16 dstPoolId;
        uint16 dstChainId;
        uint256 amount;
        uint256 minAmount;
        address payable refundAddress;
        address to;
        bytes payload;
    }

    struct VoucherObject {
        uint256 vouchers;
        uint256 optimalDstBandwidth;
        bool swap;
    }

    struct PoolObject {
        uint16 poolId;
        address poolAddress;
        uint256 totalWeight;
        uint256 totalLiquidity;
        uint256 undistributedVouchers;
    }

    struct ChainData {
        uint16 srcPoolId;
        uint16 srcChainId;
        uint16 dstPoolId;
        uint16 dstChainId;
    }

    struct SwapMessage {
        uint16 srcChainId;
        uint16 srcPoolId;
        uint16 dstPoolId;
        address receiver;
        uint256 amount;
        uint256 fee;
        uint256 vouchers;
        uint256 optimalDstBandwidth;
        bytes32 id;
        bytes payload;
    }

    struct ReceiveSwapMessage {
        uint16 srcPoolId;
        uint16 dstPoolId;
        uint16 srcChainId;
        address receiver;
        uint256 amount;
        uint256 fee;
        uint256 vouchers;
        uint256 optimalDstBandwidth;
    }

    struct LiquidityMessage {
        uint16 srcPoolId;
        uint16 dstPoolId;
        uint256 vouchers;
        uint256 optimalDstBandwidth;
        bytes32 id;
    }

    function receiveVouchers(
        uint16 _srcChainId,
        uint16 _srcPoolId,
        uint16 _dstPoolId,
        uint256 _vouchers,
        uint256 _optimalDstBandwidth,
        bool _swap
    ) external;

    function swapRemote(
        uint16 _srcPoolId,
        uint16 _dstPoolId,
        uint16 _srcChainId,
        address _to,
        uint256 _amount,
        uint256 _fee,
        uint256 _vouchers,
        uint256 _optimalDstBandwidth
    ) external;

    enum MESSAGE_TYPE {
        NONE,
        SWAP,
        ADD_LIQUIDITY
    }

    function swap(SwapParams memory swapParams) external payable returns (bytes32);

    function getPool(uint16 _poolId) external view returns (PoolObject memory);
}

File 12 of 15 : IBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import "./ILayerZeroReceiver.sol";
import "./ILayerZeroEndpoint.sol";
import "./ILayerZeroUserApplicationConfig.sol";
import "./IAssetRouter.sol";

interface IBridge is ILayerZeroReceiver, ILayerZeroUserApplicationConfig {
    function lzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload
    ) external;

    // function swap(
    //     IAssetRouter.SwapParams memory _swapParams,
    //     IAssetRouter.CreditObj memory _c,
    //     IAssetRouter.SwapObj memory _s
    // ) external payable;

    // function sendVouchers(
    //     uint16 _chainId,
    //     uint16 _srcPoolId,
    //     uint16 _dstPoolId,
    //     address payable _refundAddress,
    //     IAssetRouter.VoucherObject memory _c
    // ) external payable;

    function nextNonce(uint16 dstChain_) external view returns (uint256);

    function getReceivedSwaps(uint16 _srcChainId, bytes32 _id) external view returns (IAssetRouter.SwapMessage memory);

    function getReceivedLiquidity(uint16 srcChain_, bytes32 id_)
        external
        view
        returns (IAssetRouter.LiquidityMessage memory);

    function dispatchMessage(
        uint16 _chainId,
        IAssetRouter.MESSAGE_TYPE _type,
        address payable _refundAddress,
        bytes memory _payload
    ) external payable;

    function quoteLayerZeroFee(
        uint16 _chainId,
        IAssetRouter.MESSAGE_TYPE _type,
        bytes memory _payload
    ) external view returns (uint256, uint256);
}

File 13 of 15 : ILayerZeroEndpoint.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.5.0;

import "./ILayerZeroUserApplicationConfig.sol";

interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
    // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
    // @param _dstChainId - the destination chain identifier
    // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
    // @param _payload - a custom bytes payload to send to the destination contract
    // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
    // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
    // @param _adapterParams - parameters for custom functionality. ie: pay for a specified destination gasAmount, or receive airdropped native gas from the relayer on destination
    function send(
        uint16 _dstChainId,
        bytes calldata _destination,
        bytes calldata _payload,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes calldata _adapterParams
    ) external payable;

    // @notice used by the messaging library to publish verified payload
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source contract (as bytes) at the source chain
    // @param _dstAddress - the address on destination chain
    // @param _nonce - the unbound message ordering nonce
    // @param _gasLimit - the gas limit for external contract execution
    // @param _payload - verified payload to send to the destination contract
    function receivePayload(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        address _dstAddress,
        uint64 _nonce,
        uint256 _gasLimit,
        bytes calldata _payload
    ) external;

    // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);

    // @notice get the outboundNonce from this source chain which, consequently, is always an EVM
    // @param _srcAddress - the source chain contract address
    function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);

    // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery
    // @param _dstChainId - the destination chain identifier
    // @param _userApplication - the user app address on this EVM chain
    // @param _payload - the custom message to send over LayerZero
    // @param _payInZRO - if false, user app pays the protocol fee in native token
    // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain
    function estimateFees(
        uint16 _dstChainId,
        address _userApplication,
        bytes calldata _payload,
        bool _payInZRO,
        bytes calldata _adapterParam
    ) external view returns (uint256 nativeFee, uint256 zroFee);

    // @notice get this Endpoint's immutable source identifier
    function getChainId() external view returns (uint16);

    // @notice the interface to retry failed message on this Endpoint destination
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    // @param _payload - the payload to be retried
    function retryPayload(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        bytes calldata _payload
    ) external;

    // @notice query if any STORED payload (message blocking) at the endpoint.
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);

    // @notice query if the _libraryAddress is valid for sending msgs.
    // @param _userApplication - the user app address on this EVM chain
    function getSendLibraryAddress(address _userApplication) external view returns (address);

    // @notice query if the _libraryAddress is valid for receiving msgs.
    // @param _userApplication - the user app address on this EVM chain
    function getReceiveLibraryAddress(address _userApplication) external view returns (address);

    // @notice query if the non-reentrancy guard for send() is on
    // @return true if the guard is on. false otherwise
    function isSendingPayload() external view returns (bool);

    // @notice query if the non-reentrancy guard for receive() is on
    // @return true if the guard is on. false otherwise
    function isReceivingPayload() external view returns (bool);

    // @notice get the configuration of the LayerZero messaging library of the specified version
    // @param _version - messaging library version
    // @param _chainId - the chainId for the pending config change
    // @param _userApplication - the contract address of the user application
    // @param _configType - type of configuration. every messaging library has its own convention.
    function getConfig(
        uint16 _version,
        uint16 _chainId,
        address _userApplication,
        uint256 _configType
    ) external view returns (bytes memory);

    // @notice get the send() LayerZero messaging library version
    // @param _userApplication - the contract address of the user application
    function getSendVersion(address _userApplication) external view returns (uint16);

    // @notice get the lzReceive() LayerZero messaging library version
    // @param _userApplication - the contract address of the user application
    function getReceiveVersion(address _userApplication) external view returns (uint16);
}

File 14 of 15 : ILayerZeroReceiver.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.5.0;

interface ILayerZeroReceiver {
    // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
    // @param _srcChainId - the source endpoint identifier
    // @param _srcAddress - the source sending contract address from the source chain
    // @param _nonce - the ordered message nonce
    // @param _payload - the signed payload is the UA bytes has encoded to be sent
    function lzReceive(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) external;
}

File 15 of 15 : ILayerZeroUserApplicationConfig.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.5.0;

interface ILayerZeroUserApplicationConfig {
    // @notice set the configuration of the LayerZero messaging library of the specified version
    // @param _version - messaging library version
    // @param _chainId - the chainId for the pending config change
    // @param _configType - type of configuration. every messaging library has its own convention.
    // @param _config - configuration in the bytes. can encode arbitrary content.
    function setConfig(
        uint16 _version,
        uint16 _chainId,
        uint256 _configType,
        bytes calldata _config
    ) external;

    // @notice set the send() LayerZero messaging library version to _version
    // @param _version - new messaging library version
    function setSendVersion(uint16 _version) external;

    // @notice set the lzReceive() LayerZero messaging library version to _version
    // @param _version - new messaging library version
    function setReceiveVersion(uint16 _version) external;

    // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload
    // @param _srcChainId - the chainId of the source chain
    // @param _srcAddress - the contract address of the source contract at the source chain
    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 800
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_layerZeroEndpoint","type":"address"},{"internalType":"address","name":"_router","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BridgeMismatch","type":"error"},{"inputs":[],"name":"InsufficientAccess","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"InsuficientFee","type":"error"},{"inputs":[],"name":"NotLayerZero","type":"error"},{"inputs":[],"name":"SliceBoundsError","type":"error"},{"inputs":[],"name":"SliceOverflow","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"srcPoolId","type":"uint16"},{"internalType":"uint16","name":"dstPoolId","type":"uint16"},{"internalType":"uint256","name":"vouchers","type":"uint256"},{"internalType":"uint256","name":"optimalDstBandwidth","type":"uint256"},{"internalType":"bytes32","name":"id","type":"bytes32"}],"indexed":false,"internalType":"struct IAssetRouter.LiquidityMessage","name":"_message","type":"tuple"}],"name":"LiquidityMessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"chainId","type":"uint16"},{"indexed":true,"internalType":"enum IAssetRouter.MESSAGE_TYPE","name":"type_","type":"uint8"},{"indexed":true,"internalType":"address","name":"refundAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"}],"name":"MessageDispatched","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"uint16","name":"srcPoolId","type":"uint16"},{"internalType":"uint16","name":"dstPoolId","type":"uint16"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"vouchers","type":"uint256"},{"internalType":"uint256","name":"optimalDstBandwidth","type":"uint256"},{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"payload","type":"bytes"}],"indexed":false,"internalType":"struct IAssetRouter.SwapMessage","name":"_message","type":"tuple"}],"name":"SwapMessageReceived","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROUTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveTokenSpender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"bridgeLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"enum IAssetRouter.MESSAGE_TYPE","name":"_type","type":"uint8"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"dispatchMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"failedMessages","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"enum IAssetRouter.MESSAGE_TYPE","name":"","type":"uint8"}],"name":"gasLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChain_","type":"uint16"},{"internalType":"bytes32","name":"id_","type":"bytes32"}],"name":"getReceivedLiquidity","outputs":[{"components":[{"internalType":"uint16","name":"srcPoolId","type":"uint16"},{"internalType":"uint16","name":"dstPoolId","type":"uint16"},{"internalType":"uint256","name":"vouchers","type":"uint256"},{"internalType":"uint256","name":"optimalDstBandwidth","type":"uint256"},{"internalType":"bytes32","name":"id","type":"bytes32"}],"internalType":"struct IAssetRouter.LiquidityMessage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChain_","type":"uint16"},{"internalType":"bytes32","name":"id_","type":"bytes32"}],"name":"getReceivedSwaps","outputs":[{"components":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"uint16","name":"srcPoolId","type":"uint16"},{"internalType":"uint16","name":"dstPoolId","type":"uint16"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"vouchers","type":"uint256"},{"internalType":"uint256","name":"optimalDstBandwidth","type":"uint256"},{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"payload","type":"bytes"}],"internalType":"struct IAssetRouter.SwapMessage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"layerZeroEndpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddressBytes_","type":"bytes"},{"internalType":"uint64","name":"nonce_","type":"uint64"},{"internalType":"bytes","name":"payload_","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dstChain_","type":"uint16"}],"name":"nextNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddressBytes_","type":"bytes"},{"internalType":"bytes","name":"payload_","type":"bytes"}],"name":"nonBlockingReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"enum IAssetRouter.MESSAGE_TYPE","name":"_type","type":"uint8"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"quoteLayerZeroFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IAssetRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"bytes","name":"_bridgeAddress","type":"bytes"}],"name":"setBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"_configType","type":"uint256"},{"internalType":"bytes","name":"_config","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"enum IAssetRouter.MESSAGE_TYPE","name":"_functionType","type":"uint8"},{"internalType":"uint256","name":"_gasAmount","type":"uint256"}],"name":"setGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAssetRouter","name":"_newRouter","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"setUseLayerZeroToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"useLayerZeroToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60a06040523480156200001157600080fd5b5060405162002f3d38038062002f3d833981016040819052620000349162000167565b6001600160a01b03828116608052600380546001600160a01b031916918316919091179055620000666000336200009a565b620000927f7a05a596cb0ce7fdea8a1e1ec73be300bdb35097c944ce1897202f7a13122eb2336200009a565b50506200019f565b620000a68282620000aa565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000a6576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001063390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b03811681146200016257600080fd5b919050565b600080604083850312156200017b57600080fd5b62000186836200014a565b915062000196602084016200014a565b90509250929050565b608051612d43620001fa6000396000818161028001528181610760015281816108eb01528181610978015281816109d101528181610b3c01528181610d6501528181610e330152818161117601526112350152612d436000f3fe6080604052600436106101cc5760003560e01c80638c7ae0fc116100f7578063c93f3d0611610095578063d7d3c3b911610064578063d7d3c3b9146106d5578063d88d15c7146106f5578063f887ea4014610715578063fc8691081461073557600080fd5b8063c93f3d0614610633578063cbed8b9c14610668578063ce3d9fe614610688578063d547741f146106b557600080fd5b806396806f7a116100d157806396806f7a146105cb578063a217fddf146105de578063c0d78655146105f3578063c213dc2b1461061357600080fd5b80638c7ae0fc146105395780638e3b5d6a1461055a57806391d148541461058757600080fd5b8063248a9ca31161016f57806342d65a8d1161013e57806342d65a8d146103be57806343b18009146103de5780635a98218d146103fe5780635b8c41e6146104ea57600080fd5b8063248a9ca31461031a5780632f2ff15d1461034a57806330d643b51461036a57806336568abe1461039e57600080fd5b806307968db1116101ab57806307968db11461026e57806307e0db17146102ba57806310ddb137146102da5780631a3635f4146102fa57600080fd5b80621d3567146101d157806301ffc9a7146101f35780630242205414610228575b600080fd5b3480156101dd57600080fd5b506101f16101ec366004611ff4565b610755565b005b3480156101ff57600080fd5b5061021361020e36600461207d565b610890565b60405190151581526020015b60405180910390f35b34801561023457600080fd5b506102606102433660046120b6565b600260209081526000928352604080842090915290825290205481565b60405190815260200161021f565b34801561027a57600080fd5b506102a27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161021f565b3480156102c657600080fd5b506101f16102d53660046120e9565b6108c7565b3480156102e657600080fd5b506101f16102f53660046120e9565b610954565b34801561030657600080fd5b506102606103153660046120e9565b6109af565b34801561032657600080fd5b50610260610335366004612104565b60009081526020819052604090206001015490565b34801561035657600080fd5b506101f1610365366004612132565b610a5f565b34801561037657600080fd5b506102607f7a05a596cb0ce7fdea8a1e1ec73be300bdb35097c944ce1897202f7a13122eb281565b3480156103aa57600080fd5b506101f16103b9366004612132565b610a89565b3480156103ca57600080fd5b506101f16103d93660046121ab565b610b1a565b3480156103ea57600080fd5b506101f16103f93660046121ab565b610bad565b34801561040a57600080fd5b506104a06104193660046121fe565b6040805160a08082018352600080835260208084018290528385018290526060808501839052608094850183905261ffff978816835260068252858320968352958152908490208451928301855280548088168452620100009004909616908201526001850154928101929092526002840154928201929092526003909201549082015290565b60405161021f9190600060a08201905061ffff8084511683528060208501511660208401525060408301516040830152606083015160608301526080830151608083015292915050565b3480156104f657600080fd5b50610260610505366004612228565b6004602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561054557600080fd5b5060035461021390600160a01b900460ff1681565b34801561056657600080fd5b5061057a6105753660046120e9565b610bff565b60405161021f91906122da565b34801561059357600080fd5b506102136105a2366004612132565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6101f16105d93660046122ed565b610c99565b3480156105ea57600080fd5b50610260600081565b3480156105ff57600080fd5b506101f161060e366004612352565b610f07565b34801561061f57600080fd5b506101f161062e36600461237d565b610f4d565b34801561063f57600080fd5b5061065361064e36600461239a565b610f92565b6040805192835260208301919091520161021f565b34801561067457600080fd5b506101f16106833660046123f8565b611213565b34801561069457600080fd5b506106a86106a33660046121fe565b6112ac565b60405161021f9190612467565b3480156106c157600080fd5b506101f16106d0366004612132565b611454565b3480156106e157600080fd5b506101f16106f0366004612519565b611479565b34801561070157600080fd5b506101f161071036600461255a565b6114f7565b34801561072157600080fd5b506003546102a2906001600160a01b031681565b34801561074157600080fd5b506101f16107503660046125c4565b6115da565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461079e576040516376ee248960e11b815260040160405180910390fd5b60405163d88d15c760e01b8152309063d88d15c7906107c590879087908690600401612600565b600060405180830381600087803b1580156107df57600080fd5b505af19250505080156107f0575060015b61088a578080519060200120600460008661ffff1661ffff168152602001908152602001600020846040516108259190612639565b90815260408051918290036020908101832067ffffffffffffffff87166000908152915220919091557fe6f254030bcb01ffd20558175c13fcaed6d1520be7becee4c961b65f79243b0d90610881908690869086908690612655565b60405180910390a15b50505050565b60006001600160e01b03198216637965db0b60e01b14806108c157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60006108d281611637565b6040516307e0db1760e01b815261ffff831660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906307e0db17906024015b600060405180830381600087803b15801561093857600080fd5b505af115801561094c573d6000803e3d6000fd5b505050505050565b600061095f81611637565b6040516310ddb13760e01b815261ffff831660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906310ddb1379060240161091e565b604051630f428ae960e31b815261ffff821660048201523060248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690637a14574890604401602060405180830381865afa158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a44919061269f565b610a4f9060016126d2565b67ffffffffffffffff1692915050565b600082815260208190526040902060010154610a7a81611637565b610a848383611644565b505050565b6001600160a01b0381163314610b0c5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610b1682826116e2565b5050565b6000610b2581611637565b6040516342d65a8d60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342d65a8d90610b7590879087908790600401612723565b600060405180830381600087803b158015610b8f57600080fd5b505af1158015610ba3573d6000803e3d6000fd5b5050505050505050565b6000610bb881611637565b828230604051602001610bcd9392919061274a565b60408051601f1981840301815291815261ffff8616600090815260016020522090610bf890826127f0565b5050505050565b60016020526000908152604090208054610c1890612770565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4490612770565b8015610c915780601f10610c6657610100808354040283529160200191610c91565b820191906000526020600020905b815481529060010190602001808311610c7457829003601f168201915b505050505081565b7f7a05a596cb0ce7fdea8a1e1ec73be300bdb35097c944ce1897202f7a13122eb2610cc381611637565b61ffff8516600090815260026020819052604082206001929183919083908990811115610cf257610cf26128b0565b6002811115610d0357610d036128b0565b815260200190815260200160002054604051602001610d3b92919060f09290921b6001600160f01b0319168252600282015260220190565b60408051601f198184030181529082905263040a7bb160e41b825291506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340a7bb1090610da2908b9030908a90879089906004016128c6565b6040805180830381865afa158015610dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de29190612918565b50905034811115610e09576040516305bf2bf960e31b815260048101829052602401610b03565b61ffff881660009081526001602052604090819020905162c5803160e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163c5803100913491610e73918d91908b908d9030908b9060040161293c565b6000604051808303818588803b158015610e8c57600080fd5b505af1158015610ea0573d6000803e3d6000fd5b5050505050856001600160a01b0316876002811115610ec157610ec16128b0565b8961ffff167fa7f690e8475fb6847476d5ac16c81be25113400c1eba46447cb99b2d08e73eda88604051610ef591906122da565b60405180910390a45050505050505050565b6000610f1281611637565b50600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000610f5881611637565b5060038054911515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b604080516020810190915260008082529081906001856002811115610fb957610fb96128b0565b0361102c57600161ffff80306000198060001980306001806001604051602001610fe69493929190612a21565b604051602081830303815290604052805190602001208c6040516020016110169a99989796959493929190612a94565b60405160208183030381529060405290506110db565b6002856002811115611040576110406128b0565b0361109357600261ffff80600019803060018060016040516020016110689493929190612a21565b6040516020818303038152906040528051906020012060405160200161101696959493929190612b1c565b60405162461bcd60e51b815260206004820152601160248201527f696e76616c6964206f7065726174696f6e0000000000000000000000000000006044820152606401610b03565b61ffff8616600090815260026020819052604082206001929183919083908a9081111561110a5761110a6128b0565b600281111561111b5761111b6128b0565b81526020019081526020016000205460405160200161115392919060f09290921b6001600160f01b0319168252600282015260220190565b60408051808303601f190181529082905260035463040a7bb160e41b83529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916340a7bb10916111c4918c9130918991600160a01b900460ff169088906004016128c6565b6040805180830381865afa1580156111e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112049190612918565b94509450505050935093915050565b600061121e81611637565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbed8b9c906112729089908990899089908990600401612b61565b600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b50505050505050505050565b61131a604051806101400160405280600061ffff168152602001600061ffff168152602001600061ffff16815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008019168152602001606081525090565b61ffff838116600090815260056020818152604080842087855282529283902083516101408101855281548087168252620100008104871693820193909352640100000000830490951693850193909352660100000000000090046001600160a01b0316606084015260018201546080840152600282015460a0840152600382015460c0840152600482015460e0840152810154610100830152600681018054610120840191906113ca90612770565b80601f01602080910402602001604051908101604052809291908181526020018280546113f690612770565b80156114435780601f1061141857610100808354040283529160200191611443565b820191906000526020600020905b81548152906001019060200180831161142657829003601f168201915b505050505081525050905092915050565b60008281526020819052604090206001015461146f81611637565b610a8483836116e2565b600061148481611637565b60405163095ea7b360e01b81526001600160a01b0384811660048301526024820184905285169063095ea7b3906044016020604051808303816000875af11580156114d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf89190612b8f565b33301480159061153657503360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16155b1561155457604051630318bf7160e11b815260040160405180910390fd5b61ffff83166000908152600160205260409020805461157290612770565b905082511415806115b2575061ffff831660009081526001602052604090819020905161159f9190612bac565b6040518091039020828051906020012014155b156115d05760405163328d48b560e21b815260040160405180910390fd5b610a848382611761565b60006115e581611637565b61ffff84166000908152600260208190526040822084929091869081111561160f5761160f6128b0565b6002811115611620576116206128b0565b815260208101919091526040016000205550505050565b6116418133611b15565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610b16576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561169e3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610b16576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001818101519060ff8216900361197657600061177d83611b88565b61ffff80861680835260009081526005602081815260408084206101008701805186529083529381902086518154938801519288015160608901516001600160a01b03166601000000000000027fffffffffffff0000000000000000000000000000000000000000ffffffffffff91891664010000000002919091167fffffffffffff00000000000000000000000000000000000000000000ffffffff948916620100000263ffffffff1990961692909816919091179390931791909116949094171783556080840151600184015560a0840151600284015560c0840151600384015560e084015160048401559051908201556101208201519192508291600682019061188a90826127f0565b505060035460208301516040808501516060860151608087015160a088015160c089015160e08a0151955163e239564b60e01b815261ffff97881660048201529487166024860152958c1660448501526001600160a01b039283166064850152608484019190915260a483015260c482019390935260e48101919091529116915063e239564b9061010401600060405180830381600087803b15801561192f57600080fd5b505af1158015611943573d6000803e3d6000fd5b505050507fd732fc2ee46630cf48960a3ea67c4074ce30bfa31598cd356c3fbf0caaae68e3816040516108819190612467565b8060ff16600203610a84576040805160a08101825260008082526020808301828152838501838152606085018481526080860185815260038a81015160058c015160258d015160458e015160658f015161ffff9485168d529284168952908752855283528c8116808952600688528a892084518a52909752898820895181549751831662010000810263ffffffff199099169190931690811797909717815594516001860181905593516002860181905592519482019490945554885163904217c360e01b81526004810196909652602486019490945260448501929092526064840152608483015260a48201839052935192936001600160a01b03169263904217c39260c48084019391929182900301818387803b158015611a9857600080fd5b505af1158015611aac573d6000803e3d6000fd5b505060408051845161ffff908116825260208087015190911690820152818501519181019190915260608085015190820152608080850151908201527f78c8ab1693335bd131a40f718895fa4ba22422a3c1ca6d775316b3b7880dfbe5925060a0019050610881565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610b1657611b4681611c98565b611b51836020611caa565b604051602001611b62929190612c22565b60408051601f198184030181529082905262461bcd60e51b8252610b03916004016122da565b611bf6604051806101400160405280600061ffff168152602001600061ffff168152602001600061ffff16815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008019168152602001606081525090565b600080600080600080600080611c1a8a60b9808d51611c159190612ca3565b611e5a565b6101208a015250505050600386015160058701516019880151603989015160598a015160798b015160998c015160b9909c015161ffff96871660208d01529590941660408b01526001600160a01b0390921660608a0152608089015260a088015260c087015260e08601969096525050505061010081019190915290565b60606108c16001600160a01b03831660145b60606000611cb9836002612cb6565b611cc4906002612ccd565b67ffffffffffffffff811115611cdc57611cdc611f3b565b6040519080825280601f01601f191660200182016040528015611d06576020820181803683370190505b509050600360fc1b81600081518110611d2157611d21612ce0565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611d5057611d50612ce0565b60200101906001600160f81b031916908160001a9053506000611d74846002612cb6565b611d7f906001612ccd565b90505b6001811115611e04577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611dc057611dc0612ce0565b1a60f81b828281518110611dd657611dd6612ce0565b60200101906001600160f81b031916908160001a90535060049490941c93611dfd81612cf6565b9050611d82565b508315611e535760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610b03565b9392505050565b606081611e6881601f612ccd565b1015611e87576040516323d5783d60e11b815260040160405180910390fd5b611e918284612ccd565b84511015611eb257604051634cbc026360e11b815260040160405180910390fd5b606082158015611ed15760405191506000825260208201604052611f1b565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611f0a578051835260209283019201611ef2565b5050858452601f01601f1916604052505b50949350505050565b803561ffff81168114611f3657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611f6257600080fd5b813567ffffffffffffffff80821115611f7d57611f7d611f3b565b604051601f8301601f19908116603f01168101908282118183101715611fa557611fa5611f3b565b81604052838152866020858801011115611fbe57600080fd5b836020870160208301376000602085830101528094505050505092915050565b67ffffffffffffffff8116811461164157600080fd5b6000806000806080858703121561200a57600080fd5b61201385611f24565b9350602085013567ffffffffffffffff8082111561203057600080fd5b61203c88838901611f51565b94506040870135915061204e82611fde565b9092506060860135908082111561206457600080fd5b5061207187828801611f51565b91505092959194509250565b60006020828403121561208f57600080fd5b81356001600160e01b031981168114611e5357600080fd5b803560038110611f3657600080fd5b600080604083850312156120c957600080fd5b6120d283611f24565b91506120e0602084016120a7565b90509250929050565b6000602082840312156120fb57600080fd5b611e5382611f24565b60006020828403121561211657600080fd5b5035919050565b6001600160a01b038116811461164157600080fd5b6000806040838503121561214557600080fd5b8235915060208301356121578161211d565b809150509250929050565b60008083601f84011261217457600080fd5b50813567ffffffffffffffff81111561218c57600080fd5b6020830191508360208285010111156121a457600080fd5b9250929050565b6000806000604084860312156121c057600080fd5b6121c984611f24565b9250602084013567ffffffffffffffff8111156121e557600080fd5b6121f186828701612162565b9497909650939450505050565b6000806040838503121561221157600080fd5b61221a83611f24565b946020939093013593505050565b60008060006060848603121561223d57600080fd5b61224684611f24565b9250602084013567ffffffffffffffff81111561226257600080fd5b61226e86828701611f51565b925050604084013561227f81611fde565b809150509250925092565b60005b838110156122a557818101518382015260200161228d565b50506000910152565b600081518084526122c681602086016020860161228a565b601f01601f19169290920160200192915050565b602081526000611e5360208301846122ae565b6000806000806080858703121561230357600080fd5b61230c85611f24565b935061231a602086016120a7565b9250604085013561232a8161211d565b9150606085013567ffffffffffffffff81111561234657600080fd5b61207187828801611f51565b60006020828403121561236457600080fd5b8135611e538161211d565b801515811461164157600080fd5b60006020828403121561238f57600080fd5b8135611e538161236f565b6000806000606084860312156123af57600080fd5b6123b884611f24565b92506123c6602085016120a7565b9150604084013567ffffffffffffffff8111156123e257600080fd5b6123ee86828701611f51565b9150509250925092565b60008060008060006080868803121561241057600080fd5b61241986611f24565b945061242760208701611f24565b935060408601359250606086013567ffffffffffffffff81111561244a57600080fd5b61245688828901612162565b969995985093965092949392505050565b6020815261247c60208201835161ffff169052565b60006020830151612493604084018261ffff169052565b50604083015161ffff811660608401525060608301516001600160a01b038116608084015250608083015160a083015260a083015160c083015260c083015160e083015260e08301516101008181850152808501519150506101208181850152808501519150506101408081850152506125116101608401826122ae565b949350505050565b60008060006060848603121561252e57600080fd5b83356125398161211d565b925060208401356125498161211d565b929592945050506040919091013590565b60008060006060848603121561256f57600080fd5b61257884611f24565b9250602084013567ffffffffffffffff8082111561259557600080fd5b6125a187838801611f51565b935060408601359150808211156125b757600080fd5b506123ee86828701611f51565b6000806000606084860312156125d957600080fd5b6125e284611f24565b92506125f0602085016120a7565b9150604084013590509250925092565b61ffff8416815260606020820152600061261d60608301856122ae565b828103604084015261262f81856122ae565b9695505050505050565b6000825161264b81846020870161228a565b9190910192915050565b61ffff8516815260806020820152600061267260808301866122ae565b67ffffffffffffffff85166040840152828103606084015261269481856122ae565b979650505050505050565b6000602082840312156126b157600080fd5b8151611e5381611fde565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156126f3576126f36126bc565b5092915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff841681526040602082015260006127416040830184866126fa565b95945050505050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b600181811c9082168061278457607f821691505b6020821081036127a457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610a8457600081815260208120601f850160051c810160208610156127d15750805b601f850160051c820191505b8181101561094c578281556001016127dd565b815167ffffffffffffffff81111561280a5761280a611f3b565b61281e816128188454612770565b846127aa565b602080601f831160018114612853576000841561283b5750858301515b600019600386901b1c1916600185901b17855561094c565b600085815260208120601f198616915b8281101561288257888601518255948401946001909101908401612863565b50858210156128a05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b61ffff861681526001600160a01b038516602082015260a0604082015260006128f260a08301866122ae565b8415156060840152828103608084015261290c81856122ae565b98975050505050505050565b6000806040838503121561292b57600080fd5b505080516020909101519092909150565b61ffff871681526000602060c0818401526000885461295a81612770565b8060c087015260e060018084166000811461297c5760018114612996576129c4565b60ff1985168984015283151560051b8901830195506129c4565b8d6000528660002060005b858110156129bc5781548b82018601529083019088016129a1565b8a0184019650505b505050505083810360408501526129db81896122ae565b9150506129f360608401876001600160a01b03169052565b6001600160a01b038516608084015282810360a0840152612a1481856122ae565b9998505050505050505050565b6001600160a01b038516815260ff8481166020830152831660408201526080810160038310612a6057634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b60038110612a8d57634e487b7160e01b600052602160045260246000fd5b60f81b9052565b612a9e818c612a6f565b600061ffff60f01b808c60f01b166001840152808b60f01b166003840152506bffffffffffffffffffffffff198960601b1660058301528760198301528660398301528560598301528460798301528360998301528251612b068160b985016020870161228a565b9190910160b9019b9a5050505050505050505050565b612b268188612a6f565b6001600160f01b031960f096871b811660018301529490951b9093166003850152600584019190915260258301526045820152606501919050565b600061ffff8088168352808716602084015250846040830152608060608301526126946080830184866126fa565b600060208284031215612ba157600080fd5b8151611e538161236f565b6000808354612bba81612770565b60018281168015612bd25760018114612be757612c16565b60ff1984168752821515830287019450612c16565b8760005260208060002060005b85811015612c0d5781548a820152908401908201612bf4565b50505082870194505b50929695505050505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612c5a81601785016020880161228a565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351612c9781602884016020880161228a565b01602801949350505050565b818103818111156108c1576108c16126bc565b80820281158282048414176108c1576108c16126bc565b808201808211156108c1576108c16126bc565b634e487b7160e01b600052603260045260246000fd5b600081612d0557612d056126bc565b50600019019056fea26469706673582212207a06c0463363659ee2827b7860bef4c6df29f825f134c0603e1a4a0d907c9ce764736f6c63430008130033000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc10000000000000000000000009731f8a3b2a9ee5e017483e6b4b62a9ac1af532d

Deployed Bytecode

0x6080604052600436106101cc5760003560e01c80638c7ae0fc116100f7578063c93f3d0611610095578063d7d3c3b911610064578063d7d3c3b9146106d5578063d88d15c7146106f5578063f887ea4014610715578063fc8691081461073557600080fd5b8063c93f3d0614610633578063cbed8b9c14610668578063ce3d9fe614610688578063d547741f146106b557600080fd5b806396806f7a116100d157806396806f7a146105cb578063a217fddf146105de578063c0d78655146105f3578063c213dc2b1461061357600080fd5b80638c7ae0fc146105395780638e3b5d6a1461055a57806391d148541461058757600080fd5b8063248a9ca31161016f57806342d65a8d1161013e57806342d65a8d146103be57806343b18009146103de5780635a98218d146103fe5780635b8c41e6146104ea57600080fd5b8063248a9ca31461031a5780632f2ff15d1461034a57806330d643b51461036a57806336568abe1461039e57600080fd5b806307968db1116101ab57806307968db11461026e57806307e0db17146102ba57806310ddb137146102da5780631a3635f4146102fa57600080fd5b80621d3567146101d157806301ffc9a7146101f35780630242205414610228575b600080fd5b3480156101dd57600080fd5b506101f16101ec366004611ff4565b610755565b005b3480156101ff57600080fd5b5061021361020e36600461207d565b610890565b60405190151581526020015b60405180910390f35b34801561023457600080fd5b506102606102433660046120b6565b600260209081526000928352604080842090915290825290205481565b60405190815260200161021f565b34801561027a57600080fd5b506102a27f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc181565b6040516001600160a01b03909116815260200161021f565b3480156102c657600080fd5b506101f16102d53660046120e9565b6108c7565b3480156102e657600080fd5b506101f16102f53660046120e9565b610954565b34801561030657600080fd5b506102606103153660046120e9565b6109af565b34801561032657600080fd5b50610260610335366004612104565b60009081526020819052604090206001015490565b34801561035657600080fd5b506101f1610365366004612132565b610a5f565b34801561037657600080fd5b506102607f7a05a596cb0ce7fdea8a1e1ec73be300bdb35097c944ce1897202f7a13122eb281565b3480156103aa57600080fd5b506101f16103b9366004612132565b610a89565b3480156103ca57600080fd5b506101f16103d93660046121ab565b610b1a565b3480156103ea57600080fd5b506101f16103f93660046121ab565b610bad565b34801561040a57600080fd5b506104a06104193660046121fe565b6040805160a08082018352600080835260208084018290528385018290526060808501839052608094850183905261ffff978816835260068252858320968352958152908490208451928301855280548088168452620100009004909616908201526001850154928101929092526002840154928201929092526003909201549082015290565b60405161021f9190600060a08201905061ffff8084511683528060208501511660208401525060408301516040830152606083015160608301526080830151608083015292915050565b3480156104f657600080fd5b50610260610505366004612228565b6004602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561054557600080fd5b5060035461021390600160a01b900460ff1681565b34801561056657600080fd5b5061057a6105753660046120e9565b610bff565b60405161021f91906122da565b34801561059357600080fd5b506102136105a2366004612132565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6101f16105d93660046122ed565b610c99565b3480156105ea57600080fd5b50610260600081565b3480156105ff57600080fd5b506101f161060e366004612352565b610f07565b34801561061f57600080fd5b506101f161062e36600461237d565b610f4d565b34801561063f57600080fd5b5061065361064e36600461239a565b610f92565b6040805192835260208301919091520161021f565b34801561067457600080fd5b506101f16106833660046123f8565b611213565b34801561069457600080fd5b506106a86106a33660046121fe565b6112ac565b60405161021f9190612467565b3480156106c157600080fd5b506101f16106d0366004612132565b611454565b3480156106e157600080fd5b506101f16106f0366004612519565b611479565b34801561070157600080fd5b506101f161071036600461255a565b6114f7565b34801561072157600080fd5b506003546102a2906001600160a01b031681565b34801561074157600080fd5b506101f16107503660046125c4565b6115da565b336001600160a01b037f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc1161461079e576040516376ee248960e11b815260040160405180910390fd5b60405163d88d15c760e01b8152309063d88d15c7906107c590879087908690600401612600565b600060405180830381600087803b1580156107df57600080fd5b505af19250505080156107f0575060015b61088a578080519060200120600460008661ffff1661ffff168152602001908152602001600020846040516108259190612639565b90815260408051918290036020908101832067ffffffffffffffff87166000908152915220919091557fe6f254030bcb01ffd20558175c13fcaed6d1520be7becee4c961b65f79243b0d90610881908690869086908690612655565b60405180910390a15b50505050565b60006001600160e01b03198216637965db0b60e01b14806108c157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60006108d281611637565b6040516307e0db1760e01b815261ffff831660048201527f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc16001600160a01b0316906307e0db17906024015b600060405180830381600087803b15801561093857600080fd5b505af115801561094c573d6000803e3d6000fd5b505050505050565b600061095f81611637565b6040516310ddb13760e01b815261ffff831660048201527f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc16001600160a01b0316906310ddb1379060240161091e565b604051630f428ae960e31b815261ffff821660048201523060248201526000907f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc16001600160a01b031690637a14574890604401602060405180830381865afa158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a44919061269f565b610a4f9060016126d2565b67ffffffffffffffff1692915050565b600082815260208190526040902060010154610a7a81611637565b610a848383611644565b505050565b6001600160a01b0381163314610b0c5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b610b1682826116e2565b5050565b6000610b2581611637565b6040516342d65a8d60e01b81526001600160a01b037f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc116906342d65a8d90610b7590879087908790600401612723565b600060405180830381600087803b158015610b8f57600080fd5b505af1158015610ba3573d6000803e3d6000fd5b5050505050505050565b6000610bb881611637565b828230604051602001610bcd9392919061274a565b60408051601f1981840301815291815261ffff8616600090815260016020522090610bf890826127f0565b5050505050565b60016020526000908152604090208054610c1890612770565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4490612770565b8015610c915780601f10610c6657610100808354040283529160200191610c91565b820191906000526020600020905b815481529060010190602001808311610c7457829003601f168201915b505050505081565b7f7a05a596cb0ce7fdea8a1e1ec73be300bdb35097c944ce1897202f7a13122eb2610cc381611637565b61ffff8516600090815260026020819052604082206001929183919083908990811115610cf257610cf26128b0565b6002811115610d0357610d036128b0565b815260200190815260200160002054604051602001610d3b92919060f09290921b6001600160f01b0319168252600282015260220190565b60408051601f198184030181529082905263040a7bb160e41b825291506000906001600160a01b037f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc116906340a7bb1090610da2908b9030908a90879089906004016128c6565b6040805180830381865afa158015610dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de29190612918565b50905034811115610e09576040516305bf2bf960e31b815260048101829052602401610b03565b61ffff881660009081526001602052604090819020905162c5803160e81b81526001600160a01b037f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc1169163c5803100913491610e73918d91908b908d9030908b9060040161293c565b6000604051808303818588803b158015610e8c57600080fd5b505af1158015610ea0573d6000803e3d6000fd5b5050505050856001600160a01b0316876002811115610ec157610ec16128b0565b8961ffff167fa7f690e8475fb6847476d5ac16c81be25113400c1eba46447cb99b2d08e73eda88604051610ef591906122da565b60405180910390a45050505050505050565b6000610f1281611637565b50600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000610f5881611637565b5060038054911515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b604080516020810190915260008082529081906001856002811115610fb957610fb96128b0565b0361102c57600161ffff80306000198060001980306001806001604051602001610fe69493929190612a21565b604051602081830303815290604052805190602001208c6040516020016110169a99989796959493929190612a94565b60405160208183030381529060405290506110db565b6002856002811115611040576110406128b0565b0361109357600261ffff80600019803060018060016040516020016110689493929190612a21565b6040516020818303038152906040528051906020012060405160200161101696959493929190612b1c565b60405162461bcd60e51b815260206004820152601160248201527f696e76616c6964206f7065726174696f6e0000000000000000000000000000006044820152606401610b03565b61ffff8616600090815260026020819052604082206001929183919083908a9081111561110a5761110a6128b0565b600281111561111b5761111b6128b0565b81526020019081526020016000205460405160200161115392919060f09290921b6001600160f01b0319168252600282015260220190565b60408051808303601f190181529082905260035463040a7bb160e41b83529092507f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc16001600160a01b0316916340a7bb10916111c4918c9130918991600160a01b900460ff169088906004016128c6565b6040805180830381865afa1580156111e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112049190612918565b94509450505050935093915050565b600061121e81611637565b6040516332fb62e760e21b81526001600160a01b037f000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc1169063cbed8b9c906112729089908990899089908990600401612b61565b600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b50505050505050505050565b61131a604051806101400160405280600061ffff168152602001600061ffff168152602001600061ffff16815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008019168152602001606081525090565b61ffff838116600090815260056020818152604080842087855282529283902083516101408101855281548087168252620100008104871693820193909352640100000000830490951693850193909352660100000000000090046001600160a01b0316606084015260018201546080840152600282015460a0840152600382015460c0840152600482015460e0840152810154610100830152600681018054610120840191906113ca90612770565b80601f01602080910402602001604051908101604052809291908181526020018280546113f690612770565b80156114435780601f1061141857610100808354040283529160200191611443565b820191906000526020600020905b81548152906001019060200180831161142657829003601f168201915b505050505081525050905092915050565b60008281526020819052604090206001015461146f81611637565b610a8483836116e2565b600061148481611637565b60405163095ea7b360e01b81526001600160a01b0384811660048301526024820184905285169063095ea7b3906044016020604051808303816000875af11580156114d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf89190612b8f565b33301480159061153657503360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16155b1561155457604051630318bf7160e11b815260040160405180910390fd5b61ffff83166000908152600160205260409020805461157290612770565b905082511415806115b2575061ffff831660009081526001602052604090819020905161159f9190612bac565b6040518091039020828051906020012014155b156115d05760405163328d48b560e21b815260040160405180910390fd5b610a848382611761565b60006115e581611637565b61ffff84166000908152600260208190526040822084929091869081111561160f5761160f6128b0565b6002811115611620576116206128b0565b815260208101919091526040016000205550505050565b6116418133611b15565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610b16576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561169e3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610b16576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001818101519060ff8216900361197657600061177d83611b88565b61ffff80861680835260009081526005602081815260408084206101008701805186529083529381902086518154938801519288015160608901516001600160a01b03166601000000000000027fffffffffffff0000000000000000000000000000000000000000ffffffffffff91891664010000000002919091167fffffffffffff00000000000000000000000000000000000000000000ffffffff948916620100000263ffffffff1990961692909816919091179390931791909116949094171783556080840151600184015560a0840151600284015560c0840151600384015560e084015160048401559051908201556101208201519192508291600682019061188a90826127f0565b505060035460208301516040808501516060860151608087015160a088015160c089015160e08a0151955163e239564b60e01b815261ffff97881660048201529487166024860152958c1660448501526001600160a01b039283166064850152608484019190915260a483015260c482019390935260e48101919091529116915063e239564b9061010401600060405180830381600087803b15801561192f57600080fd5b505af1158015611943573d6000803e3d6000fd5b505050507fd732fc2ee46630cf48960a3ea67c4074ce30bfa31598cd356c3fbf0caaae68e3816040516108819190612467565b8060ff16600203610a84576040805160a08101825260008082526020808301828152838501838152606085018481526080860185815260038a81015160058c015160258d015160458e015160658f015161ffff9485168d529284168952908752855283528c8116808952600688528a892084518a52909752898820895181549751831662010000810263ffffffff199099169190931690811797909717815594516001860181905593516002860181905592519482019490945554885163904217c360e01b81526004810196909652602486019490945260448501929092526064840152608483015260a48201839052935192936001600160a01b03169263904217c39260c48084019391929182900301818387803b158015611a9857600080fd5b505af1158015611aac573d6000803e3d6000fd5b505060408051845161ffff908116825260208087015190911690820152818501519181019190915260608085015190820152608080850151908201527f78c8ab1693335bd131a40f718895fa4ba22422a3c1ca6d775316b3b7880dfbe5925060a0019050610881565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610b1657611b4681611c98565b611b51836020611caa565b604051602001611b62929190612c22565b60408051601f198184030181529082905262461bcd60e51b8252610b03916004016122da565b611bf6604051806101400160405280600061ffff168152602001600061ffff168152602001600061ffff16815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008019168152602001606081525090565b600080600080600080600080611c1a8a60b9808d51611c159190612ca3565b611e5a565b6101208a015250505050600386015160058701516019880151603989015160598a015160798b015160998c015160b9909c015161ffff96871660208d01529590941660408b01526001600160a01b0390921660608a0152608089015260a088015260c087015260e08601969096525050505061010081019190915290565b60606108c16001600160a01b03831660145b60606000611cb9836002612cb6565b611cc4906002612ccd565b67ffffffffffffffff811115611cdc57611cdc611f3b565b6040519080825280601f01601f191660200182016040528015611d06576020820181803683370190505b509050600360fc1b81600081518110611d2157611d21612ce0565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611d5057611d50612ce0565b60200101906001600160f81b031916908160001a9053506000611d74846002612cb6565b611d7f906001612ccd565b90505b6001811115611e04577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611dc057611dc0612ce0565b1a60f81b828281518110611dd657611dd6612ce0565b60200101906001600160f81b031916908160001a90535060049490941c93611dfd81612cf6565b9050611d82565b508315611e535760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610b03565b9392505050565b606081611e6881601f612ccd565b1015611e87576040516323d5783d60e11b815260040160405180910390fd5b611e918284612ccd565b84511015611eb257604051634cbc026360e11b815260040160405180910390fd5b606082158015611ed15760405191506000825260208201604052611f1b565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611f0a578051835260209283019201611ef2565b5050858452601f01601f1916604052505b50949350505050565b803561ffff81168114611f3657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611f6257600080fd5b813567ffffffffffffffff80821115611f7d57611f7d611f3b565b604051601f8301601f19908116603f01168101908282118183101715611fa557611fa5611f3b565b81604052838152866020858801011115611fbe57600080fd5b836020870160208301376000602085830101528094505050505092915050565b67ffffffffffffffff8116811461164157600080fd5b6000806000806080858703121561200a57600080fd5b61201385611f24565b9350602085013567ffffffffffffffff8082111561203057600080fd5b61203c88838901611f51565b94506040870135915061204e82611fde565b9092506060860135908082111561206457600080fd5b5061207187828801611f51565b91505092959194509250565b60006020828403121561208f57600080fd5b81356001600160e01b031981168114611e5357600080fd5b803560038110611f3657600080fd5b600080604083850312156120c957600080fd5b6120d283611f24565b91506120e0602084016120a7565b90509250929050565b6000602082840312156120fb57600080fd5b611e5382611f24565b60006020828403121561211657600080fd5b5035919050565b6001600160a01b038116811461164157600080fd5b6000806040838503121561214557600080fd5b8235915060208301356121578161211d565b809150509250929050565b60008083601f84011261217457600080fd5b50813567ffffffffffffffff81111561218c57600080fd5b6020830191508360208285010111156121a457600080fd5b9250929050565b6000806000604084860312156121c057600080fd5b6121c984611f24565b9250602084013567ffffffffffffffff8111156121e557600080fd5b6121f186828701612162565b9497909650939450505050565b6000806040838503121561221157600080fd5b61221a83611f24565b946020939093013593505050565b60008060006060848603121561223d57600080fd5b61224684611f24565b9250602084013567ffffffffffffffff81111561226257600080fd5b61226e86828701611f51565b925050604084013561227f81611fde565b809150509250925092565b60005b838110156122a557818101518382015260200161228d565b50506000910152565b600081518084526122c681602086016020860161228a565b601f01601f19169290920160200192915050565b602081526000611e5360208301846122ae565b6000806000806080858703121561230357600080fd5b61230c85611f24565b935061231a602086016120a7565b9250604085013561232a8161211d565b9150606085013567ffffffffffffffff81111561234657600080fd5b61207187828801611f51565b60006020828403121561236457600080fd5b8135611e538161211d565b801515811461164157600080fd5b60006020828403121561238f57600080fd5b8135611e538161236f565b6000806000606084860312156123af57600080fd5b6123b884611f24565b92506123c6602085016120a7565b9150604084013567ffffffffffffffff8111156123e257600080fd5b6123ee86828701611f51565b9150509250925092565b60008060008060006080868803121561241057600080fd5b61241986611f24565b945061242760208701611f24565b935060408601359250606086013567ffffffffffffffff81111561244a57600080fd5b61245688828901612162565b969995985093965092949392505050565b6020815261247c60208201835161ffff169052565b60006020830151612493604084018261ffff169052565b50604083015161ffff811660608401525060608301516001600160a01b038116608084015250608083015160a083015260a083015160c083015260c083015160e083015260e08301516101008181850152808501519150506101208181850152808501519150506101408081850152506125116101608401826122ae565b949350505050565b60008060006060848603121561252e57600080fd5b83356125398161211d565b925060208401356125498161211d565b929592945050506040919091013590565b60008060006060848603121561256f57600080fd5b61257884611f24565b9250602084013567ffffffffffffffff8082111561259557600080fd5b6125a187838801611f51565b935060408601359150808211156125b757600080fd5b506123ee86828701611f51565b6000806000606084860312156125d957600080fd5b6125e284611f24565b92506125f0602085016120a7565b9150604084013590509250925092565b61ffff8416815260606020820152600061261d60608301856122ae565b828103604084015261262f81856122ae565b9695505050505050565b6000825161264b81846020870161228a565b9190910192915050565b61ffff8516815260806020820152600061267260808301866122ae565b67ffffffffffffffff85166040840152828103606084015261269481856122ae565b979650505050505050565b6000602082840312156126b157600080fd5b8151611e5381611fde565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156126f3576126f36126bc565b5092915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff841681526040602082015260006127416040830184866126fa565b95945050505050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b600181811c9082168061278457607f821691505b6020821081036127a457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610a8457600081815260208120601f850160051c810160208610156127d15750805b601f850160051c820191505b8181101561094c578281556001016127dd565b815167ffffffffffffffff81111561280a5761280a611f3b565b61281e816128188454612770565b846127aa565b602080601f831160018114612853576000841561283b5750858301515b600019600386901b1c1916600185901b17855561094c565b600085815260208120601f198616915b8281101561288257888601518255948401946001909101908401612863565b50858210156128a05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b61ffff861681526001600160a01b038516602082015260a0604082015260006128f260a08301866122ae565b8415156060840152828103608084015261290c81856122ae565b98975050505050505050565b6000806040838503121561292b57600080fd5b505080516020909101519092909150565b61ffff871681526000602060c0818401526000885461295a81612770565b8060c087015260e060018084166000811461297c5760018114612996576129c4565b60ff1985168984015283151560051b8901830195506129c4565b8d6000528660002060005b858110156129bc5781548b82018601529083019088016129a1565b8a0184019650505b505050505083810360408501526129db81896122ae565b9150506129f360608401876001600160a01b03169052565b6001600160a01b038516608084015282810360a0840152612a1481856122ae565b9998505050505050505050565b6001600160a01b038516815260ff8481166020830152831660408201526080810160038310612a6057634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b60038110612a8d57634e487b7160e01b600052602160045260246000fd5b60f81b9052565b612a9e818c612a6f565b600061ffff60f01b808c60f01b166001840152808b60f01b166003840152506bffffffffffffffffffffffff198960601b1660058301528760198301528660398301528560598301528460798301528360998301528251612b068160b985016020870161228a565b9190910160b9019b9a5050505050505050505050565b612b268188612a6f565b6001600160f01b031960f096871b811660018301529490951b9093166003850152600584019190915260258301526045820152606501919050565b600061ffff8088168352808716602084015250846040830152608060608301526126946080830184866126fa565b600060208284031215612ba157600080fd5b8151611e538161236f565b6000808354612bba81612770565b60018281168015612bd25760018114612be757612c16565b60ff1984168752821515830287019450612c16565b8760005260208060002060005b85811015612c0d5781548a820152908401908201612bf4565b50505082870194505b50929695505050505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612c5a81601785016020880161228a565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351612c9781602884016020880161228a565b01602801949350505050565b818103818111156108c1576108c16126bc565b80820281158282048414176108c1576108c16126bc565b808201808211156108c1576108c16126bc565b634e487b7160e01b600052603260045260246000fd5b600081612d0557612d056126bc565b50600019019056fea26469706673582212207a06c0463363659ee2827b7860bef4c6df29f825f134c0603e1a4a0d907c9ce764736f6c63430008130033

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

000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc10000000000000000000000009731f8a3b2a9ee5e017483e6b4b62a9ac1af532d

-----Decoded View---------------
Arg [0] : _layerZeroEndpoint (address): 0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1
Arg [1] : _router (address): 0x9731F8a3B2a9EE5e017483e6b4B62a9aC1af532D

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000ae92d5ad7583ad66e49a0c67bad18f6ba52dddc1
Arg [1] : 0000000000000000000000009731f8a3b2a9ee5e017483e6b4b62a9ac1af532d


Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading