Contract 0x461a8878060aa45fa685732bff654ca1fdef2830

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x15480a6173ad814c33c8d6e26bc91e05289f40164905cf1b8dfa3d1f6bdca626Update Swap Rate184222932023-03-25 21:27:102 days 1 hr ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0xb5ee66b14f3582292618043de289433085490d84af7a9b5e47cee1aeb068c17cUpdate Swap Rate184222922023-03-25 21:27:052 days 1 hr ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x90b205a8b4fb5acf80c8685f90867edef0ab0ee9b0b438e15889336e705c4b11Update Swap Rate184222902023-03-25 21:26:552 days 1 hr ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x1d91d18ae7fdca110a0640d88a79df7f04f0d4e1cac6602bd80837fdfd47ef2bUpdate Swap Rate184222882023-03-25 21:26:452 days 1 hr ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x0a01c6c7d364d08ef0a76dd6d16d8ce6bf60d0ecc3ddac3ebe2b1ab76a7ceaa7Update Swap Rate184222872023-03-25 21:26:402 days 1 hr ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002051855
0x8d17919e6ea372466f5c2371525d3953f0f9875b69c0fb9d164822ac0366c6dbUpdate Swap Rate184222852023-03-25 21:26:302 days 1 hr ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002053415
0x5cb86f003bacab39e57b9ac5df0a5b101cab2e914c71f863595204edd77c10e3Update Swap Rate183109232023-03-19 10:46:188 days 12 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x677aa2676170857ed3fa71ea692f12f0b87fe463b7c8f3ffc9db0607cf4660ffUpdate Swap Rate183102102023-03-19 9:46:538 days 13 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0xc1e0c86235dd8a678075038f70b25f469ee811ba7e5c3de0f5ce4b35b7a403eaUpdate Swap Rate183087752023-03-19 7:47:188 days 15 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x639012fc16598b4d63a52f21a3028162c6ab2c7d2a4726b1c2d5c350bdf264c7Update Swap Rate183087742023-03-19 7:47:138 days 15 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x871a8fafbef600698e40dda5a0a480916cb99e089a6f5701250ed9f467b6a179Update Swap Rate183035522023-03-19 0:32:038 days 22 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x64d503680ed4906e94875197d3f6cc3907ba33a9b2c3650696ff511ac1e1d47eUpdate Swap Rate183035502023-03-19 0:31:538 days 22 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0xe012c0968a13322514deefbf7bd48f27aaf5cc7206811b8d565130219a910ca0Update Swap Rate183035482023-03-19 0:31:438 days 22 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x0719e8e3aedf1e680624eb1c5bc194637e2f9fc4f4c79599a4768b7eee151ebcUpdate Swap Rate183035472023-03-19 0:31:388 days 22 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002051855
0x0abf735d06a207a72230f2577fcd302678b5cc9c88d11ebb909282ed19724e03Update Swap Rate183035452023-03-19 0:31:288 days 22 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002053415
0x01314e2f922c68e49f142e78a0d89b4631396858bb91a66b319ca7c9f08ce523Update Swap Rate183035432023-03-19 0:31:188 days 22 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002053415
0x6ece6d84e7cf6e26c1c04263b1eea17263926a77e3b623bfee9963eeda0c0256Update Swap Rate182893052023-03-18 4:44:479 days 18 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0xc6e53f01ba3f16aae42124023f5cbafcdf532988deb69aa3fc8b7ecb9bd317e5Update Swap Rate182893032023-03-18 4:44:379 days 18 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x826afa6781677ad5fd8e82d10e727b9e2fa78fff08fd7b73855ce97658290205Update Swap Rate182893022023-03-18 4:44:329 days 18 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x1116786c326b103453c896708f58c07479e7dad5600ef556e10fd92886cb0c78Update Swap Rate182893002023-03-18 4:44:229 days 18 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0xcf5301a3c5470fa0842b79039a8c157b54cf7873782096a3997c42078001eec3Update Swap Rate182892982023-03-18 4:44:129 days 18 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002053415
0x9b3976bd3e7d769300300b4f114b31b4b0e4b2e21a974bf025b1cb37ca1bef4cUpdate Swap Rate182892972023-03-18 4:44:079 days 18 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002053415
0xfc207366a00bc04c03b9fa25d4d5960663e00f640c0ab8f2edd2b6b696516f18Update Swap Rate182892962023-03-18 4:44:029 days 18 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x706526adec33e9bcee44240903e79431e0964c7ad115dc726fd50dab43d6aa21Update Swap Rate182478792023-03-15 19:12:3312 days 3 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
0x0a0e27df10b4bacf66b14b49da0c46454730bb058859ad9258fea90772dc44fdUpdate Swap Rate182478782023-03-15 19:12:2812 days 3 hrs ago0x2005ef38fde789c281fdd9b2faf6a5dc215dd6dc IN  0x461a8878060aa45fa685732bff654ca1fdef28300 CELO0.0002052635
[ Download CSV Export 
Latest 3 internal transactions
Parent Txn Hash Block From To Value
0x269f35b635ff064baea266ff2d1b58d57e79180586107412ab040a19471fc575179856892023-02-28 15:02:5627 days 8 hrs ago 0x461a8878060aa45fa685732bff654ca1fdef28300x49887a216375fded17dc1aaad4920c37772656140.05 CELO
0x5490a06128ba86f42ae495178eba81d0a9fe5ed3a36e696a2c523d36466c52ce179856652023-02-28 15:00:5627 days 8 hrs ago 0x461a8878060aa45fa685732bff654ca1fdef28300x49887a216375fded17dc1aaad4920c37772656140.05 CELO
0x156318ddd3d1e2760cab65cd580abc5e313de5cdd90a72faca7ddc99fea8d2c2179856442023-02-28 14:59:1127 days 8 hrs ago 0x461a8878060aa45fa685732bff654ca1fdef28300x49887a216375fded17dc1aaad4920c37772656140.05 CELO
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TokenBridgeRelayer

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Apache-2.0 license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 16 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 2 of 16 : 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 3 of 16 : draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 4 of 16 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 5 of 16 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 6 of 16 : ITokenBridge.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

import "./IWETH.sol";
import "./IWormhole.sol";

interface ITokenBridge {
    struct Transfer {
        uint8 payloadID;
        uint256 amount;
        bytes32 tokenAddress;
        uint16 tokenChain;
        bytes32 to;
        uint16 toChain;
        uint256 fee;
    }

    struct TransferWithPayload {
        uint8 payloadID;
        uint256 amount;
        bytes32 tokenAddress;
        uint16 tokenChain;
        bytes32 to;
        uint16 toChain;
        bytes32 fromAddress;
        bytes payload;
    }

    struct AssetMeta {
        uint8 payloadID;
        bytes32 tokenAddress;
        uint16 tokenChain;
        uint8 decimals;
        bytes32 symbol;
        bytes32 name;
    }

    struct RegisterChain {
        bytes32 module;
        uint8 action;
        uint16 chainId;

        uint16 emitterChainID;
        bytes32 emitterAddress;
    }

     struct UpgradeContract {
        bytes32 module;
        uint8 action;
        uint16 chainId;

        bytes32 newContract;
    }

    struct RecoverChainId {
        bytes32 module;
        uint8 action;

        uint256 evmChainId;
        uint16 newChainId;
    }

    event ContractUpgraded(address indexed oldContract, address indexed newContract);

    function _parseTransferCommon(bytes memory encoded) external pure returns (Transfer memory transfer);

    function attestToken(address tokenAddress, uint32 nonce) external payable returns (uint64 sequence);

    function wrapAndTransferETH(uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce) external payable returns (uint64 sequence);

    function wrapAndTransferETHWithPayload(uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload) external payable returns (uint64 sequence);

    function transferTokens(address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce) external payable returns (uint64 sequence);

    function transferTokensWithPayload(address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload) external payable returns (uint64 sequence);

    function updateWrapped(bytes memory encodedVm) external returns (address token);

    function createWrapped(bytes memory encodedVm) external returns (address token);

    function completeTransferWithPayload(bytes memory encodedVm) external returns (bytes memory);

    function completeTransferAndUnwrapETHWithPayload(bytes memory encodedVm) external returns (bytes memory);

    function completeTransfer(bytes memory encodedVm) external;

    function completeTransferAndUnwrapETH(bytes memory encodedVm) external;

    function encodeAssetMeta(AssetMeta memory meta) external pure returns (bytes memory encoded);

    function encodeTransfer(Transfer memory transfer) external pure returns (bytes memory encoded);

    function encodeTransferWithPayload(TransferWithPayload memory transfer) external pure returns (bytes memory encoded);

    function parsePayloadID(bytes memory encoded) external pure returns (uint8 payloadID);

    function parseAssetMeta(bytes memory encoded) external pure returns (AssetMeta memory meta);

    function parseTransfer(bytes memory encoded) external pure returns (Transfer memory transfer);

    function parseTransferWithPayload(bytes memory encoded) external pure returns (TransferWithPayload memory transfer);

    function governanceActionIsConsumed(bytes32 hash) external view returns (bool);

    function isInitialized(address impl) external view returns (bool);

    function isTransferCompleted(bytes32 hash) external view returns (bool);

    function wormhole() external view returns (IWormhole);

    function chainId() external view returns (uint16);

    function evmChainId() external view returns (uint256);

    function isFork() external view returns (bool);

    function governanceChainId() external view returns (uint16);

    function governanceContract() external view returns (bytes32);

    function wrappedAsset(uint16 tokenChainId, bytes32 tokenAddress) external view returns (address);

    function bridgeContracts(uint16 chainId_) external view returns (bytes32);

    function tokenImplementation() external view returns (address);

    function WETH() external view returns (IWETH);

    function outstandingBridged(address token) external view returns (uint256);

    function isWrappedAsset(address token) external view returns (bool);

    function finality() external view returns (uint8);

    function implementation() external view returns (address);

    function initialize() external;

    function registerChain(bytes memory encodedVM) external;

    function upgrade(bytes memory encodedVM) external;

    function submitRecoverChainId(bytes memory encodedVM) external;

    function parseRegisterChain(bytes memory encoded) external pure returns (RegisterChain memory chain);

    function parseUpgrade(bytes memory encoded) external pure returns (UpgradeContract memory chain);

    function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci);
}

File 7 of 16 : IWETH.sol
// contracts/Bridge.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IWETH is IERC20 {
    function deposit() external payable;
    function withdraw(uint amount) external;
    function balanceOf() external returns (uint256);
}

File 8 of 16 : IWormhole.sol
// contracts/Messages.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

interface IWormhole {
    struct GuardianSet {
        address[] keys;
        uint32 expirationTime;
    }

    struct Signature {
        bytes32 r;
        bytes32 s;
        uint8 v;
        uint8 guardianIndex;
    }

    struct VM {
        uint8 version;
        uint32 timestamp;
        uint32 nonce;
        uint16 emitterChainId;
        bytes32 emitterAddress;
        uint64 sequence;
        uint8 consistencyLevel;
        bytes payload;

        uint32 guardianSetIndex;
        Signature[] signatures;

        bytes32 hash;
    }

    event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel);

    function publishMessage(
        uint32 nonce,
        bytes memory payload,
        uint8 consistencyLevel
    ) external payable returns (uint64 sequence);

    function parseAndVerifyVM(bytes calldata encodedVM) external view returns (VM memory vm, bool valid, string memory reason);

    function verifyVM(VM memory vm) external view returns (bool valid, string memory reason);

    function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason);

    function parseVM(bytes memory encodedVM) external pure returns (VM memory vm);

    function getGuardianSet(uint32 index) external view returns (GuardianSet memory);

    function getCurrentGuardianSetIndex() external view returns (uint32);

    function getGuardianSetExpiry() external view returns (uint32);

    function governanceActionIsConsumed(bytes32 hash) external view returns (bool);

    function isInitialized(address impl) external view returns (bool);

    function chainId() external view returns (uint16);

    function governanceChainId() external view returns (uint16);

    function governanceContract() external view returns (bytes32);

    function messageFee() external view returns (uint256);

    function evmChainId() external view returns (uint256);

    function nextSequence(address emitter) external view returns (uint64);
}

File 9 of 16 : BytesLib.sol
// SPDX-License-Identifier: Unlicense
/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */
pragma solidity >=0.8.0 <0.9.0;


library BytesLib {
    function concat(
        bytes memory _preBytes,
        bytes memory _postBytes
    )
        internal
        pure
        returns (bytes memory)
    {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(0x40, and(
              add(add(end, iszero(add(length, mload(_preBytes)))), 31),
              not(31) // Round down to the nearest 32 bytes.
            ))
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes.slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes.slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(
                            fslot,
                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                        ),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))

                for {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(
        bytes memory _bytes,
        uint256 _start,
        uint256 _length
    )
        internal
        pure
        returns (bytes memory)
    {
        require(_length + 31 >= _length, "slice_overflow");
        require(_bytes.length >= _start + _length, "slice_outOfBounds");

        bytes memory tempBytes;

        assembly {
            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)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                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)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
        require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
        require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
        require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
        require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
        require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
        require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
        require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
        require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                // the next line is the loop condition:
                // while(uint256(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(
        bytes storage _preBytes,
        bytes memory _postBytes
    )
        internal
        view
        returns (bool)
    {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes.slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes.slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while(uint256(mc < end) + cb == 2)
                        for {} eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

File 10 of 16 : TokenBridgeRelayer.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

import {IWormhole} from "../interfaces/IWormhole.sol";

import "../libraries/BytesLib.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import "./TokenBridgeRelayerGovernance.sol";
import "./TokenBridgeRelayerMessages.sol";

/**
 * @title Wormhole Token Bridge Relayer
 * @notice This contract composes on Wormhole's Token Bridge contracts to faciliate
 * one-click transfers of Token Bridge supported assets cross chain.
 */
contract TokenBridgeRelayer is TokenBridgeRelayerGovernance, TokenBridgeRelayerMessages, ReentrancyGuard {
    using BytesLib for bytes;

    constructor(
        uint16 chainId,
        address wormhole,
        address tokenBridge_,
        address wethAddress,
        bool unwrapWeth_
    ) {
        require(chainId > 0, "invalid chainId");
        require(wormhole != address(0), "invalid wormhole address");
        require(tokenBridge_ != address(0), "invalid token bridge address");
        require(wethAddress != address(0), "invalid weth address");

        // set initial state
        setOwner(msg.sender);
        setChainId(chainId);
        setWormhole(wormhole);
        setTokenBridge(tokenBridge_);
        setWethAddress(wethAddress);
        setUnwrapWethFlag(unwrapWeth_);

        // set the initial swapRate/relayer precisions to 1e8
        setSwapRatePrecision(1e8);
        setRelayerFeePrecision(1e8);
    }

    /**
     * @notice Emitted when a transfer is completed by the Wormhole token bridge
     * @param emitterChainId Wormhole chain ID of emitter contract on the source chain
     * @param emitterAddress Address (bytes32 zero-left-padded) of emitter on the source chain
     * @param sequence Sequence of the Wormhole message
     */
    event TransferRedeemed(
        uint16 indexed emitterChainId,
        bytes32 indexed emitterAddress,
        uint64 indexed sequence
    );

    /**
     * @notice Emitted when a swap is executed with an off-chain relayer
     * @param recipient Address of the recipient of the native assets
     * @param relayer Address of the relayer that performed the swap
     * @param token Address of the token being swapped
     * @param tokenAmount Amount of token being swapped
     * @param nativeAmount Amount of native assets swapped for tokens
     */
    event SwapExecuted(
        address indexed recipient,
        address indexed relayer,
        address indexed token,
        uint256 tokenAmount,
        uint256 nativeAmount
    );

    /**
     * @notice Calls Wormhole's Token Bridge contract to emit a contract-controlled
     * transfer. The transfer message includes an arbitrary payload with instructions
     * for how to handle relayer payments on the target contract and the quantity of
     * tokens to convert into native assets for the user.
     * @param token ERC20 token address to transfer cross chain.
     * @param amount Quantity of tokens to be transferred.
     * @param toNativeTokenAmount Amount of tokens to swap into native assets on
     * the target chain.
     * @param targetChain Wormhole chain ID of the target blockchain.
     * @param targetRecipient User's wallet address on the target blockchain in bytes32 format
     * (zero-left-padded).
     * @param batchId ID for Wormhole message batching
     * @return messageSequence Wormhole sequence for emitted TransferTokensWithRelay message.
     */
    function transferTokensWithRelay(
        address token,
        uint256 amount,
        uint256 toNativeTokenAmount,
        uint16 targetChain,
        bytes32 targetRecipient,
        uint32 batchId
    ) public payable nonReentrant returns (uint64 messageSequence) {
        // Cache wormhole fee and confirm that the user has passed enough
        // value to cover the wormhole protocol fee.
        uint256 wormholeFee = wormhole().messageFee();
        require(msg.value == wormholeFee, "insufficient value");

        // Cache token decimals, and remove dust from the amount argument. This
        // ensures that the dust is never transferred to this contract.
        uint8 tokenDecimals = getDecimals(token);
        amount = denormalizeAmount(
            normalizeAmount(amount, tokenDecimals),
            tokenDecimals
        );

        // Transfer tokens from user to the this contract, and
        // override amount with actual amount received.
        amount = custodyTokens(token, amount);

        // call the internal _transferTokensWithRelay function
        messageSequence = _transferTokensWithRelay(
            InternalTransferParams({
                token: token,
                amount: amount,
                tokenDecimals: tokenDecimals,
                toNativeTokenAmount: toNativeTokenAmount,
                targetChain: targetChain,
                targetRecipient: targetRecipient
            }),
            batchId,
            wormholeFee
        );
    }

    /**
     * @notice Wraps Ether and calls Wormhole's Token Bridge contract to emit
     * a contract-controlled transfer. The transfer message includes an arbitrary
     * payload with instructions for how to handle relayer payments on the target
     * contract and the quantity of tokens to convert into native assets for the user.
     * @param toNativeTokenAmount Amount of tokens to swap into native assets on
     * the target chain.
     * @param targetChain Wormhole chain ID of the target blockchain.
     * @param targetRecipient User's wallet address on the target blockchain in bytes32 format
     * (zero-left-padded).
     * @param batchId ID for Wormhole message batching
     * @return messageSequence Wormhole sequence for emitted TransferTokensWithRelay message.
     */
    function wrapAndTransferEthWithRelay(
        uint256 toNativeTokenAmount,
        uint16 targetChain,
        bytes32 targetRecipient,
        uint32 batchId
    ) public payable returns (uint64 messageSequence) {
        require(unwrapWeth(), "WETH functionality not supported");

        // Cache wormhole fee and confirm that the user has passed enough
        // value to cover the wormhole protocol fee.
        uint256 wormholeFee = wormhole().messageFee();
        require(msg.value > wormholeFee, "insufficient value");

        // remove the wormhole protocol fee from the amount
        uint256 amount = msg.value - wormholeFee;

        // refund dust
        uint256 dust = amount - denormalizeAmount(normalizeAmount(amount, 18), 18);
        if (dust > 0) {
            payable(msg.sender).transfer(dust);
        }

        // remove dust from amount and cache WETH
        uint256 amountLessDust = amount - dust;
        IWETH weth = WETH();

        // deposit into the WETH contract
        weth.deposit{
            value : amountLessDust
        }();

        // call the internal _transferTokensWithRelay function
        messageSequence = _transferTokensWithRelay(
            InternalTransferParams({
                token: address(weth),
                tokenDecimals: 18,
                amount: amountLessDust,
                toNativeTokenAmount: toNativeTokenAmount,
                targetChain: targetChain,
                targetRecipient: targetRecipient
            }),
            batchId,
            wormholeFee
        );
    }

    function _transferTokensWithRelay(
        InternalTransferParams memory params,
        uint32 batchId,
        uint256 wormholeFee
    ) internal returns (uint64 messageSequence) {
        // sanity check function arguments
        require(isAcceptedToken(params.token), "token not accepted");
        require(
            params.targetRecipient != bytes32(0),
            "targetRecipient cannot be bytes32(0)"
        );

        /**
         * Cache the normalized amount and verify that it's nonzero.
         * The token bridge peforms the same operation before encoding
         * the amount in the `TransferWithPayload` message.
         */
        uint256 normalizedAmount = normalizeAmount(
            params.amount,
            params.tokenDecimals
        );
        require(normalizedAmount > 0, "normalized amount must be > 0");

        // normalized toNativeTokenAmount should be nonzero
        uint256 normalizedToNativeTokenAmount = normalizeAmount(
            params.toNativeTokenAmount,
            params.tokenDecimals
        );
        require(
            params.toNativeTokenAmount == 0 || normalizedToNativeTokenAmount > 0,
            "invalid toNativeTokenAmount"
        );

        // Cache the target contract address and verify that there
        // is a registered contract for the specified targetChain.
        bytes32 targetContract = getRegisteredContract(params.targetChain);
        require(targetContract != bytes32(0), "target not registered");

        // Confirm that the user has sent enough tokens to cover the native swap
        // on the target chain and to pay the relayer fee.
        uint256 normalizedRelayerFee = normalizeAmount(
            calculateRelayerFee(
                params.targetChain,
                params.token,
                params.tokenDecimals
            ),
            params.tokenDecimals
        );
        require(
            normalizedAmount > normalizedRelayerFee + normalizedToNativeTokenAmount,
            "insufficient amount"
        );

        /**
         * Encode instructions (TransferWithRelay) to send with the token transfer.
         * The `targetRecipient` address is in bytes32 format (zero-left-padded) to
         * support non-evm smart contracts that have addresses that are longer
         * than 20 bytes.
         *
         * We normalize the relayerFee and toNativeTokenAmount to support
         * non-evm smart contracts that can only handle uint64.max values.
         */
        bytes memory messagePayload = encodeTransferWithRelay(
            TransferWithRelay({
                payloadId: 1,
                targetRelayerFee: normalizedRelayerFee,
                toNativeTokenAmount: normalizedToNativeTokenAmount,
                targetRecipient: params.targetRecipient
            })
        );

        // cache TokenBridge instance
        ITokenBridge bridge = tokenBridge();

        // approve the token bridge to spend the specified tokens
        SafeERC20.safeApprove(
            IERC20(params.token),
            address(bridge),
            params.amount
        );

        /**
         * Call `transferTokensWithPayload` method on the token bridge and pay
         * the Wormhole network fee. The token bridge will emit a Wormhole
         * message with an encoded `TransferWithPayload` struct (see the
         * ITokenBridge.sol interface file in this repo).
         */
        messageSequence = bridge.transferTokensWithPayload{value: wormholeFee}(
            params.token,
            params.amount,
            params.targetChain,
            targetContract,
            batchId,
            messagePayload
        );
    }

    /**
     * @notice Calls Wormhole's Token Bridge contract to complete token transfers. Takes
     * custody of the wrapped (or released) tokens and sends the tokens to the target recipient.
     * It pays the relayer in the minted token denomination. If requested by the user,
     * it will perform a swap with the off-chain relayer to provide the user with native assets.
     * If the `token` being transferred is WETH, the contract will unwrap native assets and send
     * the transferred amount to the recipient and pay the relayer in native assets.
     * @dev reverts if:
     * - the transferred token is not accepted by this contract
     * - the transffered token is not attested on this blockchain's Token Bridge contract
     * - the emitter of the transfer message is not registered with this contract
     * - the relayer fails to provide enough native assets to faciliate a native swap
     * - the recipient attempts to swap native assets when performing a self redemption
     * @param encodedTransferMessage Attested `TransferWithPayload` wormhole message.
     */
    function completeTransferWithRelay(bytes calldata encodedTransferMessage) public payable {
        // complete the transfer by calling the token bridge
        (bytes memory payload, uint256 amount, address token) =
             _completeTransfer(encodedTransferMessage);

        // parse the payload into the `TransferWithRelay` struct
        TransferWithRelay memory transferWithRelay = decodeTransferWithRelay(
            payload
        );

        // cache the recipient address and unwrap weth flag
        address recipient = bytes32ToAddress(transferWithRelay.targetRecipient);
        bool unwrapWeth = unwrapWeth();

        // handle self redemptions
        if (msg.sender == recipient) {
            _completeSelfRedemption(
                token,
                recipient,
                amount,
                unwrapWeth
            );

            // bail out
            return;
        }

        // cache token decimals
        uint8 tokenDecimals = getDecimals(token);

        // denormalize the encoded relayerFee
        transferWithRelay.targetRelayerFee = denormalizeAmount(
            transferWithRelay.targetRelayerFee,
            tokenDecimals
        );

        // unwrap and transfer ETH
        if (token == address(WETH())) {
            _completeWethTransfer(
                amount,
                recipient,
                transferWithRelay.targetRelayerFee,
                unwrapWeth
            );

            // bail out
            return;
        }

        // handle native asset payments and refunds
        if (transferWithRelay.toNativeTokenAmount > 0) {
            // denormalize the toNativeTokenAmount
            transferWithRelay.toNativeTokenAmount = denormalizeAmount(
                transferWithRelay.toNativeTokenAmount,
                tokenDecimals
            );

            /**
             * Compute the maximum amount of tokens that the user is allowed
             * to swap for native assets.
             *
             * Override the toNativeTokenAmount in transferWithRelay if the
             * toNativeTokenAmount is greater than the maxToNativeAllowed.
             *
             * Compute the amount of native assets to send the recipient.
             */
            uint256 nativeAmountForRecipient;
            uint256 maxToNativeAllowed = calculateMaxSwapAmountIn(token);
            if (transferWithRelay.toNativeTokenAmount > maxToNativeAllowed) {
                transferWithRelay.toNativeTokenAmount = maxToNativeAllowed;
            }
            // compute amount of native asset to pay the recipient
            nativeAmountForRecipient = calculateNativeSwapAmountOut(
                token,
                transferWithRelay.toNativeTokenAmount
            );

            /**
             * The nativeAmountForRecipient can be zero if the user specifed
             * a toNativeTokenAmount that is too little to convert to native
             * asset. We need to override the toNativeTokenAmount to be zero
             * if that is the case, that way the user receives the full amount
             * of transferred tokens.
             */
            if (nativeAmountForRecipient > 0) {
                // check to see if the relayer sent enough value
                require(
                    msg.value >= nativeAmountForRecipient,
                    "insufficient native asset amount"
                );

                // refund excess native asset to relayer if applicable
                uint256 relayerRefund = msg.value - nativeAmountForRecipient;
                if (relayerRefund > 0) {
                    payable(msg.sender).transfer(relayerRefund);
                }

                // send requested native asset to target recipient
                payable(recipient).transfer(nativeAmountForRecipient);

                // emit swap event
                emit SwapExecuted(
                    recipient,
                    msg.sender,
                    token,
                    transferWithRelay.toNativeTokenAmount,
                    nativeAmountForRecipient
                );
            } else {
                // override the toNativeTokenAmount in transferWithRelay
                transferWithRelay.toNativeTokenAmount = 0;

                // refund the relayer any native asset sent to this contract
                if (msg.value > 0) {
                    payable(msg.sender).transfer(msg.value);
                }
            }
        }

        // add the token swap amount to the relayer fee
        uint256 amountForRelayer =
            transferWithRelay.targetRelayerFee + transferWithRelay.toNativeTokenAmount;

        // pay the relayer if amountForRelayer > 0
        if (amountForRelayer > 0) {
            SafeERC20.safeTransfer(
                IERC20(token),
                msg.sender,
                amountForRelayer
            );
        }

        // pay the target recipient the remaining tokens
        SafeERC20.safeTransfer(
            IERC20(token),
            recipient,
            amount - amountForRelayer
        );
    }

    function _completeTransfer(
        bytes memory encodedTransferMessage
    ) internal returns (bytes memory, uint256, address) {
        /**
         * parse the encoded Wormhole message
         *
         * SECURITY: This message not been verified by the Wormhole core layer yet.
         * The encoded payload can only be trusted once the message has been verified
         * by the Wormhole core contract. In this case, the message will be verified
         * by a call to the token bridge contract in subsequent actions.
         */
        IWormhole.VM memory parsedMessage = wormhole().parseVM(
            encodedTransferMessage
        );

        /**
         * The amount encoded in the payload could be incorrect,
         * since fee-on-transfer tokens are supported by the token bridge.
         *
         * NOTE: The token bridge truncates the encoded amount for any token
         * with decimals greater than 8. This is to support blockchains that
         * cannot handle transfer amounts exceeding max(uint64).
         */
        address localTokenAddress = fetchLocalAddressFromTransferMessage(
            parsedMessage.payload
        );
        require(isAcceptedToken(localTokenAddress), "token not registered");

        // check balance before completing the transfer
        uint256 balanceBefore = getBalance(localTokenAddress);

        // cache the token bridge instance
        ITokenBridge bridge = tokenBridge();

        /**
         * Call `completeTransferWithPayload` on the token bridge. This
         * method acts as a reentrancy protection since it does not allow
         * transfers to be redeemed more than once.
         */
        bytes memory transferPayload = bridge.completeTransferWithPayload(
            encodedTransferMessage
        );

        // compute and save the balance difference after completing the transfer
        uint256 amountReceived = getBalance(localTokenAddress) - balanceBefore;

        // parse the wormhole message payload into the `TransferWithPayload` struct
        ITokenBridge.TransferWithPayload memory transfer =
            bridge.parseTransferWithPayload(transferPayload);

        // confirm that the message sender is a registered TokenBridgeRelayer contract
        require(
            transfer.fromAddress == getRegisteredContract(parsedMessage.emitterChainId),
            "contract not registered"
        );

        // emit event with information about the TransferWithPayload message
        emit TransferRedeemed(
            parsedMessage.emitterChainId,
            parsedMessage.emitterAddress,
            parsedMessage.sequence
        );

        return (
            transfer.payload,
            amountReceived,
            localTokenAddress
        );
    }

    function _completeSelfRedemption(
        address token,
        address recipient,
        uint256 amount,
        bool unwrapWeth
    ) internal {
        // revert if the caller sends ether to this contract
        require(msg.value == 0, "recipient cannot swap native assets");

        // cache WETH instance
        IWETH weth = WETH();

        // transfer the full amount to the recipient
        if (token == address(weth) && unwrapWeth) {
            // withdraw weth and send to the recipient
            weth.withdraw(amount);
            payable(recipient).transfer(amount);
        } else {
            SafeERC20.safeTransfer(
                IERC20(token),
                recipient,
                amount
            );
        }
    }

    function _completeWethTransfer(
        uint256 amount,
        address recipient,
        uint256 relayerFee,
        bool unwrapWeth
    ) internal {
        // revert if the relayer sends ether to this contract
        require(msg.value == 0, "value must be zero");

        /**
         * Check if the weth is unwrappable. Some wrapped native assets
         * are not unwrappable (e.g. CELO) and must be transferred via
         * the ERC20 interface.
         */
        if (unwrapWeth) {
            // withdraw eth
            WETH().withdraw(amount);

            // transfer eth to recipient
            payable(recipient).transfer(amount - relayerFee);

            // transfer relayer fee to the caller
            if (relayerFee > 0) {
                payable(msg.sender).transfer(relayerFee);
            }
        } else {
            // cache WETH instance
            IWETH weth = WETH();

            // transfer the native asset to the caller
            SafeERC20.safeTransfer(
                IERC20(address(weth)),
                recipient,
                amount - relayerFee
            );

            // transfer relayer fee to the caller
            if (relayerFee > 0) {
                SafeERC20.safeTransfer(
                    IERC20(address(weth)),
                    msg.sender,
                    relayerFee
                );
            }
        }
    }

    /**
     * @notice Parses the encoded address and chainId from a `TransferWithPayload`
     * message. Finds the address of the wrapped token contract if the token is not
     * native to this chain.
     * @param payload Encoded `TransferWithPayload` message
     * @return localAddress Address of the encoded (bytes32 format) token address on
     * this chain.
     */
    function fetchLocalAddressFromTransferMessage(
        bytes memory payload
    ) public view returns (address localAddress) {
        // parse the source token address and chainId
        bytes32 sourceAddress = payload.toBytes32(33);
        uint16 tokenChain = payload.toUint16(65);

        // Fetch the wrapped address from the token bridge if the token
        // is not from this chain.
        if (tokenChain != chainId()) {
            // identify wormhole token bridge wrapper
            localAddress = tokenBridge().wrappedAsset(tokenChain, sourceAddress);
            require(localAddress != address(0), "token not attested");
        } else {
            // return the encoded address if the token is native to this chain
            localAddress = bytes32ToAddress(sourceAddress);
        }
    }

    /**
     * @notice Calculates the max amount of tokens the user can convert to
     * native assets on this chain.
     * @dev The max amount of native assets the contract will swap with the user
     * is governed by the `maxNativeSwapAmount` state variable.
     * @param token Address of token being transferred.
     * @return maxAllowed The maximum number of tokens the user is allowed to
     * swap for native assets.
     */
    function calculateMaxSwapAmountIn(
        address token
    ) public view returns (uint256 maxAllowed) {
        // fetch the decimals for the token and native token
        uint8 tokenDecimals = getDecimals(token);
        uint8 nativeDecimals = getDecimals(address(WETH()));

        if (tokenDecimals > nativeDecimals) {
            maxAllowed =
                maxNativeSwapAmount(token) * nativeSwapRate(token) *
                10 ** (tokenDecimals - nativeDecimals) / swapRatePrecision();
        } else {
            maxAllowed =
                (maxNativeSwapAmount(token) * nativeSwapRate(token)) /
                (10 ** (nativeDecimals - tokenDecimals) * swapRatePrecision());
        }
    }

    /**
     * @notice Calculates the amount of native assets that a user will receive
     * when swapping transferred tokens for native assets.
     * @param token Address of token being transferred.
     * @param toNativeAmount Quantity of tokens to be converted to native assets.
     * @return nativeAmount The exchange rate between native assets and the `toNativeAmount`
     * of transferred tokens.
     */
    function calculateNativeSwapAmountOut(
        address token,
        uint256 toNativeAmount
    ) public view returns (uint256 nativeAmount) {
        // fetch the decimals for the token and native token
        uint8 tokenDecimals = getDecimals(token);
        uint8 nativeDecimals = getDecimals(address(WETH()));

        if (tokenDecimals > nativeDecimals) {
            nativeAmount =
                swapRatePrecision() * toNativeAmount /
                (nativeSwapRate(token) * 10 ** (tokenDecimals - nativeDecimals));
        } else {
            nativeAmount =
                swapRatePrecision() * toNativeAmount *
                10 ** (nativeDecimals - tokenDecimals) /
                nativeSwapRate(token);
        }
    }

    /**
     * @notice Converts the USD denominated relayer fee into the specified token
     * denomination.
     * @param targetChainId Wormhole chain ID of the target blockchain.
     * @param token Address of token being transferred.
     * @param decimals Token decimals of token being transferred.
     * @return feeInTokenDenomination Relayer fee denominated in tokens.
     */
    function calculateRelayerFee(
        uint16 targetChainId,
        address token,
        uint8 decimals
    ) public view returns (uint256 feeInTokenDenomination) {
        // cache swap rate
        uint256 tokenSwapRate = swapRate(token);
        require(tokenSwapRate != 0, "swap rate not set");
        feeInTokenDenomination =
            10 ** decimals * relayerFee(targetChainId) * swapRatePrecision() /
            (tokenSwapRate * relayerFeePrecision());
    }

    function custodyTokens(
        address token,
        uint256 amount
    ) internal returns (uint256) {
        // query own token balance before transfer
        uint256 balanceBefore = getBalance(token);

        // deposit tokens
        SafeERC20.safeTransferFrom(
            IERC20(token),
            msg.sender,
            address(this),
            amount
        );

        // return the balance difference
        return getBalance(token) - balanceBefore;
    }

    function bytes32ToAddress(bytes32 address_) internal pure returns (address) {
        require(bytes12(address_) == 0, "invalid EVM address");
        return address(uint160(uint256(address_)));
    }

    // necessary for receiving native assets
    receive() external payable {}
}

File 11 of 16 : TokenBridgeRelayerGetters.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

import {IWormhole} from "../interfaces/IWormhole.sol";
import {ITokenBridge} from "../interfaces/ITokenBridge.sol";
import {IWETH} from "../interfaces/IWETH.sol";

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "./TokenBridgeRelayerSetters.sol";

abstract contract TokenBridgeRelayerGetters is TokenBridgeRelayerSetters {
    function owner() public view returns (address) {
        return _state.owner;
    }

    function pendingOwner() public view returns (address) {
        return _state.pendingOwner;
    }

    function wormhole() public view returns (IWormhole) {
        return IWormhole(_state.wormhole);
    }

    function tokenBridge() public view returns (ITokenBridge) {
        return ITokenBridge(payable(_state.tokenBridge));
    }

    function WETH() public view returns (IWETH) {
        return IWETH(_state.wethAddress);
    }

    function unwrapWeth() public view returns (bool) {
        return _state.unwrapWeth;
    }

    function chainId() public view returns (uint16) {
        return _state.chainId;
    }

    function getRegisteredContract(uint16 emitterChainId) public view returns (bytes32) {
        return _state.registeredContracts[emitterChainId];
    }

    function swapRatePrecision() public view returns (uint256) {
        return _state.swapRatePrecision;
    }

    function isAcceptedToken(address token) public view returns (bool) {
        return _state.acceptedTokens[token];
    }

    function getAcceptedTokensList() public view returns (address[] memory) {
        return _state.acceptedTokensList;
    }

    function relayerFeePrecision() public view returns (uint256) {
        return _state.relayerFeePrecision;
    }

    function relayerFee(uint16 chainId_) public view returns (uint256) {
        return _state.relayerFees[chainId_];
    }

    function maxNativeSwapAmount(address token) public view returns (uint256) {
        return _state.maxNativeSwapAmount[token];
    }

    function swapRate(address token) public view returns (uint256) {
        return _state.swapRates[token];
    }

    function nativeSwapRate(address token) public view returns (uint256) {
        uint256 nativeSwapRate_ = swapRate(_state.wethAddress);
        uint256 tokenSwapRate = swapRate(token);

        require(
            nativeSwapRate_ > 0 && tokenSwapRate > 0,
            "swap rate not set"
        );

        return swapRatePrecision() * nativeSwapRate_ / tokenSwapRate;
    }

    function normalizeAmount(
        uint256 amount,
        uint8 decimals
    ) public pure returns (uint256) {
        if (decimals > 8) {
            amount /= 10 ** (decimals - 8);
        }
        return amount;
    }

    function denormalizeAmount(
        uint256 amount,
        uint8 decimals
    ) public pure returns (uint256) {
        if (decimals > 8) {
            amount *= 10 ** (decimals - 8);
        }
        return amount;
    }

    function getDecimals(address token) internal view returns (uint8) {
        (,bytes memory queriedDecimals) = token.staticcall(
            abi.encodeWithSignature("decimals()")
        );
        return abi.decode(queriedDecimals, (uint8));
    }

    function getBalance(address token) internal view returns (uint256 balance) {
        // fetch the specified token balance for this contract
        (, bytes memory queriedBalance) =
            token.staticcall(
                abi.encodeWithSelector(IERC20.balanceOf.selector, address(this))
            );
        balance = abi.decode(queriedBalance, (uint256));
    }
}

File 12 of 16 : TokenBridgeRelayerGovernance.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

import {IWormhole} from "../interfaces/IWormhole.sol";

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import "./TokenBridgeRelayerGetters.sol";

abstract contract TokenBridgeRelayerGovernance is TokenBridgeRelayerGetters {
    event OwnershipTransfered(address indexed oldOwner, address indexed newOwner);
    event SwapRateUpdated(address indexed token, uint256 indexed swapRate);

    /**
     * @notice Starts the ownership transfer process of the contracts. It saves
     * an address in the pending owner state variable.
     * @param chainId_ Wormhole chain ID.
     * @param newOwner Address of the pending owner.
     */
    function submitOwnershipTransferRequest(
        uint16 chainId_,
        address newOwner
    ) public onlyOwner onlyCurrentChain(chainId_) {
        require(newOwner != address(0), "newOwner cannot equal address(0)");

        setPendingOwner(newOwner);
    }

    /**
     * @notice Cancels the ownership transfer process.
     * @dev Sets the pending owner state variable to the zero address.
     */
    function cancelOwnershipTransferRequest(
        uint16 chainId_
    ) public onlyOwner onlyCurrentChain(chainId_) {
        setPendingOwner(address(0));
    }

    /**
     * @notice Finalizes the ownership transfer to the pending owner.
     * @dev It checks that the caller is the pendingOwner to validate the wallet
     * address. It updates the owner state variable with the pendingOwner state
     * variable.
     */
    function confirmOwnershipTransferRequest() public {
        // cache the new owner address
        address newOwner = pendingOwner();

        require(msg.sender == newOwner, "caller must be pendingOwner");

        // cache currentOwner for Event
        address currentOwner = owner();

        // update the owner in the contract state and reset the pending owner
        setOwner(newOwner);
        setPendingOwner(address(0));

        emit OwnershipTransfered(currentOwner, newOwner);
    }

    /**
     * @notice Updates the unwrapWeth state variable.
     * @dev This variable should only be set to true for chains that
     * support a WETH contract. Some chains (e.g. Celo, Karura, Acala)
     * do not support a WETH contract, and the address is set as a placeholder
     * for the native asset address for swapRate lookups.
     * @param chainId_ Wormhole chain ID.
     * @param unwrapWeth_ Boolean that determines if WETH is unwrapped
     * when transferred back to its native blockchain.
     */
    function updateUnwrapWethFlag(
        uint16 chainId_,
        bool unwrapWeth_
    ) public onlyOwner onlyCurrentChain(chainId_) {
        setUnwrapWethFlag(unwrapWeth_);
    }

    /**
     * @notice Registers foreign Token Bridge Relayer contracts.
     * @param chainId_ Wormhole chain ID of the foreign contract.
     * @param contractAddress Address of the foreign contract in bytes32 format
     * (zero-left-padded address).
     */
    function registerContract(
        uint16 chainId_,
        bytes32 contractAddress
    ) public onlyOwner {
        // sanity check both input arguments
        require(
            contractAddress != bytes32(0),
            "contractAddress cannot equal bytes32(0)"
        );
        require(
            chainId_ != 0 && chainId_ != chainId(),
            "chainId_ cannot equal 0 or this chainId"
        );

        // update the registeredContracts state variable
        _registerContract(chainId_, contractAddress);
    }

    /**
     * @notice Register tokens accepted by this contract.
     * @param chainId_ Wormhole chain ID.
     * @param token Address of the token.
     */
    function registerToken(
        uint16 chainId_,
        address token
    ) public onlyOwner onlyCurrentChain(chainId_) {
        require(token != address(0), "invalid token");

        addAcceptedToken(token);
    }

    /**
     * @notice Deregister tokens accepted by this contract.
     * @dev The `removeAcceptedToken` function will revert
     * if the token is not registered.
     * @param chainId_ Wormhole chain ID.
     * @param token Address of the token.
     */
    function deregisterToken(
        uint16 chainId_,
        address token
    ) public onlyOwner onlyCurrentChain(chainId_) {
        require(token != address(0), "invalid token");

        removeAcceptedToken(token);
    }

    /**
     * @notice Updates the fee for relaying transfers to foreign contracts.
     * @param chainId_ Wormhole chain ID.
     * @param amount Amount of USD to pay the relayer upon redemption.
     * @dev The relayerFee is scaled by the relayerFeePrecision. For example,
     * if the relayerFee is $15 and the relayerFeePrecision is 1000000, the
     * relayerFee should be set to 15000000.
     */
    function updateRelayerFee(
        uint16 chainId_,
        uint256 amount
    ) public onlyOwner {
        require(chainId_ != chainId(), "invalid chain");
        require(
            getRegisteredContract(chainId_) != bytes32(0),
            "contract doesn't exist"
        );

        setRelayerFee(chainId_, amount);
    }

    /**
     * @notice Updates the precision of the relayer fee.
     * @param chainId_ Wormhole chain ID.
     * @param relayerFeePrecision_ Precision of relayer fee.
     */
    function updateRelayerFeePrecision(
        uint16 chainId_,
        uint256 relayerFeePrecision_
    ) public onlyOwner onlyCurrentChain(chainId_) {
        require(relayerFeePrecision_ > 0, "precision must be > 0");

        setRelayerFeePrecision(relayerFeePrecision_);
    }

    /**
     * @notice Updates the swap rate for specified token in USD.
     * @param chainId_ Wormhole chain ID.
     * @param token Address of the token to update the conversion rate for.
     * @param swapRate The token -> USD conversion rate.
     * @dev The swapRate is the conversion rate using asset prices denominated in
     * USD multiplied by the swapRatePrecision. For example, if the conversion
     * rate is $15 and the swapRatePrecision is 1000000, the swapRate should be set
     * to 15000000.
     */
    function updateSwapRate(
        uint16 chainId_,
        address token,
        uint256 swapRate
    ) public onlyOwner onlyCurrentChain(chainId_) {
        require(isAcceptedToken(token), "token not accepted");
        require(swapRate > 0, "swap rate must be nonzero");

        setSwapRate(token, swapRate);

        emit SwapRateUpdated(token, swapRate);
    }

    /**
     * @notice Updates the precision of the swap rate.
     * @param chainId_ Wormhole chain ID.
     * @param swapRatePrecision_ Precision of swap rate.
     */
    function updateSwapRatePrecision(
        uint16 chainId_,
        uint256 swapRatePrecision_
    ) public onlyOwner onlyCurrentChain(chainId_) {
        require(swapRatePrecision_ > 0, "precision must be > 0");

        setSwapRatePrecision(swapRatePrecision_);
    }

    /**
     * @notice Updates the max amount of native assets the contract will pay
     * to the target recipient.
     * @param chainId_ Wormhole chain ID.
     * @param token Address of the token to update the max native swap amount for.
     * @param maxAmount Max amount of native assets.
     */
    function updateMaxNativeSwapAmount(
        uint16 chainId_,
        address token,
        uint256 maxAmount
    ) public onlyOwner onlyCurrentChain(chainId_) {
        require(isAcceptedToken(token), "token not accepted");

        setMaxNativeSwapAmount(token, maxAmount);
    }

    modifier onlyOwner() {
        require(owner() == msg.sender, "caller not the owner");
        _;
    }

    modifier onlyCurrentChain(uint16 chainId_) {
        require(chainId() == chainId_, "wrong chain");
        _;
    }
}

File 13 of 16 : TokenBridgeRelayerMessages.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

import "../libraries/BytesLib.sol";

import "./TokenBridgeRelayerStructs.sol";

abstract contract TokenBridgeRelayerMessages is TokenBridgeRelayerStructs {
    using BytesLib for bytes;

    /**
     * @notice Encodes the TransferWithRelay struct into bytes.
     * @param transfer TransferWithRelay struct.
     * @return encoded TransferWithRelay struct encoded into bytes.
     */
    function encodeTransferWithRelay(
        TransferWithRelay memory transfer
    ) public pure returns (bytes memory encoded) {
       require(transfer.payloadId == 1, "invalid payloadId");
        encoded = abi.encodePacked(
            transfer.payloadId,
            transfer.targetRelayerFee,
            transfer.toNativeTokenAmount,
            transfer.targetRecipient
        );
    }

    /**
     * @notice Decodes an encoded `TransferWithRelay` struct.
     * @dev reverts if:
     * - the first byte (payloadId) does not equal 1
     * - the length of the payload has an unexpected length
     * @param encoded Encoded `TransferWithRelay` struct.
     * @return transfer `TransferTokenRelay` struct.
     */
    function decodeTransferWithRelay(
        bytes memory encoded
    ) public pure returns (TransferWithRelay memory transfer) {
        uint256 index = 0;

        // parse the payloadId
        transfer.payloadId = encoded.toUint8(index);
        index += 1;

        require(transfer.payloadId == 1, "invalid payloadId");

        // target relayer fee
        transfer.targetRelayerFee = encoded.toUint256(index);
        index += 32;

        // amount of tokens to convert to native assets
        transfer.toNativeTokenAmount = encoded.toUint256(index);
        index += 32;

        // recipient of the transfered tokens and native assets
        transfer.targetRecipient = encoded.toBytes32(index);
        index += 32;

        require(index == encoded.length, "invalid message length");
    }
}

File 14 of 16 : TokenBridgeRelayerSetters.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

import "./TokenBridgeRelayerState.sol";

abstract contract TokenBridgeRelayerSetters is TokenBridgeRelayerState {
    function setOwner(address owner_) internal {
        _state.owner = owner_;
    }

    function setPendingOwner(address pendingOwner_) internal {
        _state.pendingOwner = pendingOwner_;
    }

    function setWormhole(address wormhole_) internal {
        _state.wormhole = payable(wormhole_);
    }

    function setTokenBridge(address tokenBridge_) internal {
        _state.tokenBridge = payable(tokenBridge_);
    }

    function setUnwrapWethFlag(bool unwrapWeth_) internal {
        _state.unwrapWeth = unwrapWeth_;
    }

    function setWethAddress(address weth_) internal {
        _state.wethAddress = weth_;
    }

    function setChainId(uint16 chainId_) internal {
        _state.chainId = chainId_;
    }

    function _registerContract(uint16 chainId_, bytes32 contract_) internal {
        _state.registeredContracts[chainId_] = contract_;
    }

    function setSwapRatePrecision(uint256 precision) internal {
        _state.swapRatePrecision = precision;
    }

    function setRelayerFeePrecision(uint256 precision) internal {
        _state.relayerFeePrecision = precision;
    }

    function addAcceptedToken(address token) internal {
        require(
            _state.acceptedTokens[token] == false,
            "token already registered"
        );
        _state.acceptedTokens[token] = true;
        _state.acceptedTokensList.push(token);
    }

    function removeAcceptedToken(address token) internal {
        require(
            _state.acceptedTokens[token],
            "token not registered"
        );

        // Remove the token from the acceptedTokens mapping, and
        // clear the token's swapRate and maxNativeSwapAmount.
        _state.acceptedTokens[token] = false;
        _state.swapRates[token] = 0;
        _state.maxNativeSwapAmount[token] = 0;

        // cache array length
        uint256 length_ = _state.acceptedTokensList.length;

        // Replace `token` in the acceptedTokensList with the last
        // element in the acceptedTokensList array.
        uint256 i = 0;
        for (; i < length_;) {
            if (_state.acceptedTokensList[i] == token) {
                break;
            }
            unchecked { i += 1; }
        }

        if (i != length_) {
            if (length_ > 1) {
                _state.acceptedTokensList[i] = _state.acceptedTokensList[length_ - 1];
            }
            _state.acceptedTokensList.pop();
        }
    }

    function setRelayerFee(uint16 chainId_, uint256 fee) internal {
        _state.relayerFees[chainId_] = fee;
    }

    function setSwapRate(address token, uint256 swapRate) internal {
        _state.swapRates[token] = swapRate;
    }

    function setMaxNativeSwapAmount(address token, uint256 maximum) internal {
        _state.maxNativeSwapAmount[token] = maximum;
    }
}

File 15 of 16 : TokenBridgeRelayerState.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

import {IWormhole} from "../interfaces/IWormhole.sol";

abstract contract TokenBridgeRelayerStorage {
    struct State {
        // Wormhole chain ID of this contract
        uint16 chainId;

        // boolean to determine if weth is unwrappable
        bool unwrapWeth;

        // address of WETH on this chain
        address wethAddress;

        // owner of this contract
        address owner;

        // intermediate state when transfering contract ownership
        address pendingOwner;

        // address of the Wormhole contract on this chain
        address wormhole;

        // address of the Wormhole TokenBridge contract on this chain
        address tokenBridge;

        // precision of the nativeSwapRates, this value should NEVER be set to zero
        uint256 swapRatePrecision;

        // precision of the relayerFee, this value should NEVER be set to zero
        uint256 relayerFeePrecision;

        // Wormhole chain ID to known relayer contract address mapping
        mapping(uint16 => bytes32) registeredContracts;

        // token swap rate in USD terms
        mapping(address => uint256) swapRates;

        /**
         * Mapping of source token address to maximum native asset swap amount
         * allowed.
         */
        mapping(address => uint256) maxNativeSwapAmount;

        // mapping of chainId to relayerFee in USD
        mapping(uint16 => uint256) relayerFees;

        // accepted token to bool mapping
        mapping(address => bool) acceptedTokens;

        // list of accepted token addresses
        address[] acceptedTokensList;
    }
}

abstract contract TokenBridgeRelayerState {
    TokenBridgeRelayerStorage.State _state;
}

File 16 of 16 : TokenBridgeRelayerStructs.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

abstract contract TokenBridgeRelayerStructs {
    struct TransferWithRelay {
        uint8 payloadId; // == 1
        uint256 targetRelayerFee;
        uint256 toNativeTokenAmount;
        bytes32 targetRecipient;
    }

    struct InternalTransferParams {
        address token;
        uint8 tokenDecimals;
        uint256 amount;
        uint256 toNativeTokenAmount;
        uint16 targetChain;
        bytes32 targetRecipient;
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@solidity-parser/=node_modules/@solidity-parser/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "wormhole-solidity/=modules/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"wormhole","type":"address"},{"internalType":"address","name":"tokenBridge_","type":"address"},{"internalType":"address","name":"wethAddress","type":"address"},{"internalType":"bool","name":"unwrapWeth_","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransfered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"name":"SwapExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"swapRate","type":"uint256"}],"name":"SwapRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"emitterChainId","type":"uint16"},{"indexed":true,"internalType":"bytes32","name":"emitterAddress","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"sequence","type":"uint64"}],"name":"TransferRedeemed","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"calculateMaxSwapAmountIn","outputs":[{"internalType":"uint256","name":"maxAllowed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"toNativeAmount","type":"uint256"}],"name":"calculateNativeSwapAmountOut","outputs":[{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"targetChainId","type":"uint16"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"calculateRelayerFee","outputs":[{"internalType":"uint256","name":"feeInTokenDenomination","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"}],"name":"cancelOwnershipTransferRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedTransferMessage","type":"bytes"}],"name":"completeTransferWithRelay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"confirmOwnershipTransferRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encoded","type":"bytes"}],"name":"decodeTransferWithRelay","outputs":[{"components":[{"internalType":"uint8","name":"payloadId","type":"uint8"},{"internalType":"uint256","name":"targetRelayerFee","type":"uint256"},{"internalType":"uint256","name":"toNativeTokenAmount","type":"uint256"},{"internalType":"bytes32","name":"targetRecipient","type":"bytes32"}],"internalType":"struct TokenBridgeRelayerStructs.TransferWithRelay","name":"transfer","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"denormalizeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"address","name":"token","type":"address"}],"name":"deregisterToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"payloadId","type":"uint8"},{"internalType":"uint256","name":"targetRelayerFee","type":"uint256"},{"internalType":"uint256","name":"toNativeTokenAmount","type":"uint256"},{"internalType":"bytes32","name":"targetRecipient","type":"bytes32"}],"internalType":"struct TokenBridgeRelayerStructs.TransferWithRelay","name":"transfer","type":"tuple"}],"name":"encodeTransferWithRelay","outputs":[{"internalType":"bytes","name":"encoded","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"fetchLocalAddressFromTransferMessage","outputs":[{"internalType":"address","name":"localAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAcceptedTokensList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"emitterChainId","type":"uint16"}],"name":"getRegisteredContract","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isAcceptedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"maxNativeSwapAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"nativeSwapRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"normalizeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"bytes32","name":"contractAddress","type":"bytes32"}],"name":"registerContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"address","name":"token","type":"address"}],"name":"registerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"}],"name":"relayerFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"relayerFeePrecision","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"submitOwnershipTransferRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"swapRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapRatePrecision","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenBridge","outputs":[{"internalType":"contract ITokenBridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"toNativeTokenAmount","type":"uint256"},{"internalType":"uint16","name":"targetChain","type":"uint16"},{"internalType":"bytes32","name":"targetRecipient","type":"bytes32"},{"internalType":"uint32","name":"batchId","type":"uint32"}],"name":"transferTokensWithRelay","outputs":[{"internalType":"uint64","name":"messageSequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"unwrapWeth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"maxAmount","type":"uint256"}],"name":"updateMaxNativeSwapAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"updateRelayerFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"uint256","name":"relayerFeePrecision_","type":"uint256"}],"name":"updateRelayerFeePrecision","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"swapRate","type":"uint256"}],"name":"updateSwapRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"uint256","name":"swapRatePrecision_","type":"uint256"}],"name":"updateSwapRatePrecision","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"bool","name":"unwrapWeth_","type":"bool"}],"name":"updateUnwrapWethFlag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wormhole","outputs":[{"internalType":"contract IWormhole","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"toNativeTokenAmount","type":"uint256"},{"internalType":"uint16","name":"targetChain","type":"uint16"},{"internalType":"bytes32","name":"targetRecipient","type":"bytes32"},{"internalType":"uint32","name":"batchId","type":"uint32"}],"name":"wrapAndTransferEthWithRelay","outputs":[{"internalType":"uint64","name":"messageSequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b50604051620040b9380380620040b9833981016040819052620000349162000260565b6001600d5561ffff8516620000825760405162461bcd60e51b815260206004820152600f60248201526e1a5b9d985b1a590818da185a5b9259608a1b60448201526064015b60405180910390fd5b6001600160a01b038416620000da5760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420776f726d686f6c6520616464726573730000000000000000604482015260640162000079565b6001600160a01b038316620001325760405162461bcd60e51b815260206004820152601c60248201527f696e76616c696420746f6b656e20627269646765206164647265737300000000604482015260640162000079565b6001600160a01b0382166200018a5760405162461bcd60e51b815260206004820152601460248201527f696e76616c696420776574682061646472657373000000000000000000000000604482015260640162000079565b600180546001600160a01b031916331790556000805461ffff191661ffff8716179055600380546001600160a01b0319166001600160a01b038616179055600480546001600160a01b0319166001600160a01b038516179055600080546301000000600160b81b03191663010000006001600160a01b038516021790556000805462ff0000191662010000831515021790556200022a6305f5e100600555565b620002386305f5e100600655565b5050505050620002e0565b80516001600160a01b03811681146200025b57600080fd5b919050565b600080600080600060a086880312156200027957600080fd5b855161ffff811681146200028c57600080fd5b94506200029c6020870162000243565b9350620002ac6040870162000243565b9250620002bc6060870162000243565b915060808601518015158114620002d257600080fd5b809150509295509295909350565b613dc980620002f06000396000f3fe6080604052600436106102345760003560e01c80637c9dec7a1161012e578063a2f32c8f116100ab578063cd601c781161006f578063cd601c781461071a578063df160d761461073a578063e30c39781461075c578063f23f82ef1461077a578063fff982a81461079a57600080fd5b8063a2f32c8f14610677578063ad5c464814610697578063b5419523146106bc578063c6328a46146106dc578063c9c22f9f146106fa57600080fd5b806390a1afaa116100f257806390a1afaa146105c957806394cc743d146105e95780639a8a0592146106095780639cf278cd1461062c5780639fe089ad1461064a57600080fd5b80637c9dec7a146104f75780638335572f1461054d57806384acd1bb1461056d5780638da5cb5b1461058b5780638e151dd1146105a957600080fd5b80632def3e16116101bc5780633d62cca0116101805780633d62cca014610440578063415828bf1461047157806351e2d7b5146104865780635b9cf0e1146104a657806366775a6b146104c657600080fd5b80632def3e16146103875780632efe4f42146103a75780632f25e25f146103dd57806339ba6611146103f05780633b6e750f1461041057600080fd5b806327105ab91161020357806327105ab9146102c657806328ded8e3146102e657806329ac8361146103065780632ca8008c146103195780632d77e8fe1461034f57600080fd5b8063016aa20514610240578063038c0b66146102625780631019d654146102775780631acdab4b146102a757600080fd5b3661023b57005b600080fd5b34801561024c57600080fd5b5061026061025b3660046131a1565b6107ba565b005b34801561026e57600080fd5b50610260610884565b61028a6102853660046131ec565b610971565b6040516001600160401b0390911681526020015b60405180910390f35b3480156102b357600080fd5b506005545b60405190815260200161029e565b3480156102d257600080fd5b506102b86102e1366004613262565b610ac3565b3480156102f257600080fd5b506102b8610301366004613262565b610afd565b61028a610314366004613287565b610b2b565b34801561032557600080fd5b506102b86103343660046132d1565b6001600160a01b031660009081526008602052604090205490565b34801561035b57600080fd5b5061036f61036a3660046133c9565b610d7b565b6040516001600160a01b03909116815260200161029e565b34801561039357600080fd5b506102606103a2366004613448565b610e9b565b3480156103b357600080fd5b506102b86103c23660046132d1565b6001600160a01b031660009081526009602052604090205490565b6102606103eb366004613474565b610f59565b3480156103fc57600080fd5b506102b861040b3660046134e5565b611274565b34801561041c57600080fd5b5061043061042b3660046132d1565b611327565b604051901515815260200161029e565b34801561044c57600080fd5b506102b861045b366004613530565b61ffff1660009081526007602052604090205490565b34801561047d57600080fd5b506006546102b8565b34801561049257600080fd5b506102606104a1366004613448565b611345565b3480156104b257600080fd5b506102606104c1366004613448565b61146f565b3480156104d257600080fd5b506102b86104e1366004613530565b61ffff166000908152600a602052604090205490565b34801561050357600080fd5b506105176105123660046133c9565b611566565b60405161029e9190815160ff16815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561055957600080fd5b5061026061056836600461355b565b611697565b34801561057957600080fd5b506003546001600160a01b031661036f565b34801561059757600080fd5b506001546001600160a01b031661036f565b3480156105b557600080fd5b506102b86105c4366004613589565b61171e565b3480156105d557600080fd5b506102606105e4366004613448565b6117fe565b3480156105f557600080fd5b506102606106043660046131a1565b6118bc565b34801561061557600080fd5b5060005460405161ffff909116815260200161029e565b34801561063857600080fd5b5060005462010000900460ff16610430565b34801561065657600080fd5b5061066a6106653660046135a7565b611988565b60405161029e9190613665565b34801561068357600080fd5b50610260610692366004613530565b611a33565b3480156106a357600080fd5b50600054630100000090046001600160a01b031661036f565b3480156106c857600080fd5b506102b86106d73660046132d1565b611aaa565b3480156106e857600080fd5b506004546001600160a01b031661036f565b34801561070657600080fd5b506102606107153660046131a1565b611b44565b34801561072657600080fd5b506102b86107353660046132d1565b611c00565b34801561074657600080fd5b5061074f611ce5565b60405161029e9190613678565b34801561076857600080fd5b506002546001600160a01b031661036f565b34801561078657600080fd5b506102606107953660046136c5565b611d4a565b3480156107a657600080fd5b506102606107b53660046136c5565b611e75565b336107cd6001546001600160a01b031690565b6001600160a01b0316146107fc5760405162461bcd60e51b81526004016107f390613706565b60405180910390fd5b818061ffff1661080f60005461ffff1690565b61ffff16146108305760405162461bcd60e51b81526004016107f390613734565b6001600160a01b0382166108765760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b2103a37b5b2b760991b60448201526064016107f3565b61087f82611f29565b505050565b60006108986002546001600160a01b031690565b9050336001600160a01b038216146108f25760405162461bcd60e51b815260206004820152601b60248201527f63616c6c6572206d7573742062652070656e64696e674f776e6572000000000060448201526064016107f3565b60006109066001546001600160a01b031690565b600180546001600160a01b0319166001600160a01b038516179055905061092d60006120ce565b816001600160a01b0316816001600160a01b03167f0d18b5fd22306e373229b9439188228edca81207d1667f604daf6cef8aa3ee6760405160405180910390a35050565b600061097b6120f0565b600061098f6003546001600160a01b031690565b6001600160a01b0316631a90a2196040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f09190613759565b9050803414610a365760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742076616c756560701b60448201526064016107f3565b6000610a4189612149565b9050610a56610a508983610ac3565b82610afd565b9750610a6289896121eb565b9750610aab6040518060c001604052808b6001600160a01b031681526020018360ff1681526020018a81526020018981526020018861ffff168152602001878152508584612221565b92505050610ab96001600d55565b9695505050505050565b600060088260ff161115610af457610adc600883613788565b610ae790600a613885565b610af19084613894565b92505b50815b92915050565b600060088260ff161115610af457610b16600883613788565b610b2190600a613885565b610af190846138b6565b6000805462010000900460ff16610b845760405162461bcd60e51b815260206004820181905260248201527f574554482066756e6374696f6e616c697479206e6f7420737570706f7274656460448201526064016107f3565b6000610b986003546001600160a01b031690565b6001600160a01b0316631a90a2196040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf99190613759565b9050803411610c3f5760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742076616c756560701b60448201526064016107f3565b6000610c4b82346138cd565b90506000610c64610c5d836012610ac3565b6012610afd565b610c6e90836138cd565b90508015610ca557604051339082156108fc029083906000818181858888f19350505050158015610ca3573d6000803e3d6000fd5b505b6000610cb182846138cd565b90506000610ccf6000546001600160a01b0363010000009091041690565b9050806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d0c57600080fd5b505af1158015610d20573d6000803e3d6000fd5b5050505050610d6d6040518060c00160405280836001600160a01b03168152602001601260ff1681526020018481526020018c81526020018b61ffff1681526020018a8152508887612221565b9a9950505050505050505050565b600080610d8983602161253b565b90506000610d98846041612599565b9050610da760005461ffff1690565b61ffff168161ffff1614610e88576004546001600160a01b0316604051630ff8f14360e11b815261ffff83166004820152602481018490526001600160a01b039190911690631ff1e28690604401602060405180830381865afa158015610e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3691906138e0565b92506001600160a01b038316610e835760405162461bcd60e51b81526020600482015260126024820152711d1bdad95b881b9bdd08185d1d195cdd195960721b60448201526064016107f3565b610e94565b610e91826125f6565b92505b5050919050565b33610eae6001546001600160a01b031690565b6001600160a01b031614610ed45760405162461bcd60e51b81526004016107f390613706565b818061ffff16610ee760005461ffff1690565b61ffff1614610f085760405162461bcd60e51b81526004016107f390613734565b60008211610f505760405162461bcd60e51b81526020600482015260156024820152740707265636973696f6e206d757374206265203e203605c1b60448201526064016107f3565b61087f82600555565b6000806000610f9d85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061264a92505050565b9250925092506000610fae84611566565b90506000610fbf82606001516125f6565b90506000610fd660005460ff620100009091041690565b90506001600160a01b0382163303610ffe57610ff484838784612926565b5050505050505050565b600061100985612149565b9050611019846020015182610afd565b6020850152600054630100000090046001600160a01b03166001600160a01b0316856001600160a01b031603611064576110598684866020015185612a50565b505050505050505050565b60408401511561122b5761107c846040015182610afd565b604085015260008061108d87611c00565b905080866040015111156110a357604086018190525b6110b187876040015161171e565b915081156111ed57813410156111095760405162461bcd60e51b815260206004820181905260248201527f696e73756666696369656e74206e617469766520617373657420616d6f756e7460448201526064016107f3565b600061111583346138cd565b9050801561114c57604051339082156108fc029083906000818181858888f1935050505015801561114a573d6000803e3d6000fd5b505b6040516001600160a01b0387169084156108fc029085906000818181858888f19350505050158015611182573d6000803e3d6000fd5b50876001600160a01b0316336001600160a01b0316876001600160a01b03167f764f0dc063c06f32d89a3f3af80c0db4be8a090901f589a478b447e0a51f09f18a60400151876040516111df929190918252602082015260400190565b60405180910390a450611228565b6000604087015234156112285760405133903480156108fc02916000818181858888f19350505050158015611226573d6000803e3d6000fd5b505b50505b60008460400151856020015161124191906138fd565b9050801561125457611254863383612ba8565b6112688685611263848b6138cd565b612ba8565b50505050505050505050565b6001600160a01b038216600090815260086020526040812054806000036112d15760405162461bcd60e51b81526020600482015260116024820152701cddd85c081c985d19481b9bdd081cd95d607a1b60448201526064016107f3565b6006546112de90826138b6565b60055461ffff87166000908152600a602052604090205461130086600a613885565b61130a91906138b6565b61131491906138b6565b61131e9190613894565b95945050505050565b6001600160a01b03166000908152600b602052604090205460ff1690565b336113586001546001600160a01b031690565b6001600160a01b03161461137e5760405162461bcd60e51b81526004016107f390613706565b806113db5760405162461bcd60e51b815260206004820152602760248201527f636f6e7472616374416464726573732063616e6e6f7420657175616c206279746044820152666573333228302960c81b60648201526084016107f3565b61ffff8216158015906113f7575060005461ffff838116911614155b6114535760405162461bcd60e51b815260206004820152602760248201527f636861696e49645f2063616e6e6f7420657175616c2030206f7220746869732060448201526618da185a5b925960ca1b60648201526084016107f3565b61ffff91909116600090815260076020526040902055565b5050565b336114826001546001600160a01b031690565b6001600160a01b0316146114a85760405162461bcd60e51b81526004016107f390613706565b60005461ffff1661ffff168261ffff16036114f55760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b21031b430b4b760991b60448201526064016107f3565b61ffff821660009081526007602052604090205461154e5760405162461bcd60e51b815260206004820152601660248201527518dbdb9d1c9858dd08191bd95cdb89dd08195e1a5cdd60521b60448201526064016107f3565b61ffff919091166000908152600a6020526040902055565b6040805160808101825260008082526020820181905291810182905260608101829052906115948382612c0b565b60ff1682526115a46001826138fd565b9050816000015160ff166001146115f15760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c185e5b1bd8591259607a1b60448201526064016107f3565b6115fb8382612c67565b60208084019190915261160e90826138fd565b905061161a8382612c67565b604083015261162a6020826138fd565b9050611636838261253b565b60608301526116466020826138fd565b9050825181146116915760405162461bcd60e51b81526020600482015260166024820152750d2dcecc2d8d2c840dacae6e6c2ceca40d8cadccee8d60531b60448201526064016107f3565b50919050565b336116aa6001546001600160a01b031690565b6001600160a01b0316146116d05760405162461bcd60e51b81526004016107f390613706565b818061ffff166116e360005461ffff1690565b61ffff16146117045760405162461bcd60e51b81526004016107f390613734565b6000805462ff000019166201000084151502179055505050565b60008061172a84612149565b9050600061175061174b6000546001600160a01b0363010000009091041690565b612149565b90508060ff168260ff1611156117ad5761176a8183613788565b61177590600a613885565b61177e86611aaa565b61178891906138b6565b8461179260055490565b61179c91906138b6565b6117a69190613894565b92506117f6565b6117b685611aaa565b6117c08383613788565b6117cb90600a613885565b856117d560055490565b6117df91906138b6565b6117e991906138b6565b6117f39190613894565b92505b505092915050565b336118116001546001600160a01b031690565b6001600160a01b0316146118375760405162461bcd60e51b81526004016107f390613706565b818061ffff1661184a60005461ffff1690565b61ffff161461186b5760405162461bcd60e51b81526004016107f390613734565b600082116118b35760405162461bcd60e51b81526020600482015260156024820152740707265636973696f6e206d757374206265203e203605c1b60448201526064016107f3565b61087f82600655565b336118cf6001546001600160a01b031690565b6001600160a01b0316146118f55760405162461bcd60e51b81526004016107f390613706565b818061ffff1661190860005461ffff1690565b61ffff16146119295760405162461bcd60e51b81526004016107f390613734565b6001600160a01b03821661197f5760405162461bcd60e51b815260206004820181905260248201527f6e65774f776e65722063616e6e6f7420657175616c206164647265737328302960448201526064016107f3565b61087f826120ce565b6060816000015160ff166001146119d55760405162461bcd60e51b81526020600482015260116024820152701a5b9d985b1a59081c185e5b1bd8591259607a1b60448201526064016107f3565b815160208084015160408086015160608701519151611a1d95949192910160f89490941b6001600160f81b031916845260018401929092526021830152604182015260610190565b6040516020818303038152906040529050919050565b33611a466001546001600160a01b031690565b6001600160a01b031614611a6c5760405162461bcd60e51b81526004016107f390613706565b808061ffff16611a7f60005461ffff1690565b61ffff1614611aa05760405162461bcd60e51b81526004016107f390613734565b61146b60006120ce565b600080546001600160a01b0363010000009091048116825260086020526040808320549184168352822054600082118015611ae55750600081115b611b255760405162461bcd60e51b81526020600482015260116024820152701cddd85c081c985d19481b9bdd081cd95d607a1b60448201526064016107f3565b8082611b3060055490565b611b3a91906138b6565b610e919190613894565b33611b576001546001600160a01b031690565b6001600160a01b031614611b7d5760405162461bcd60e51b81526004016107f390613706565b818061ffff16611b9060005461ffff1690565b61ffff1614611bb15760405162461bcd60e51b81526004016107f390613734565b6001600160a01b038216611bf75760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b2103a37b5b2b760991b60448201526064016107f3565b61087f82612cbc565b600080611c0c83612149565b90506000611c2d61174b6000546001600160a01b0363010000009091041690565b90508060ff168260ff161115611c9c57600554611c4a8284613788565b611c5590600a613885565b611c5e86611aaa565b6001600160a01b038716600090815260096020526040902054611c8191906138b6565b611c8b91906138b6565b611c959190613894565b9250610e94565b600554611ca98383613788565b611cb490600a613885565b611cbe91906138b6565b611cc785611aaa565b6001600160a01b038616600090815260096020526040902054611b30565b60606000600c01805480602002602001604051908101604052809291908181526020018280548015611d4057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d22575b5050505050905090565b33611d5d6001546001600160a01b031690565b6001600160a01b031614611d835760405162461bcd60e51b81526004016107f390613706565b828061ffff16611d9660005461ffff1690565b61ffff1614611db75760405162461bcd60e51b81526004016107f390613734565b611dc083611327565b611ddc5760405162461bcd60e51b81526004016107f390613910565b60008211611e2c5760405162461bcd60e51b815260206004820152601960248201527f737761702072617465206d757374206265206e6f6e7a65726f0000000000000060448201526064016107f3565b6001600160a01b038316600081815260086020526040808220859055518492917fc6eb9fb936b61b402d503deeffc822f46492e15c2c8f079815cc4850ad7b02b091a350505050565b33611e886001546001600160a01b031690565b6001600160a01b031614611eae5760405162461bcd60e51b81526004016107f390613706565b828061ffff16611ec160005461ffff1690565b61ffff1614611ee25760405162461bcd60e51b81526004016107f390613734565b611eeb83611327565b611f075760405162461bcd60e51b81526004016107f390613910565b6001600160a01b03831660009081526009602052604090208290555b50505050565b6001600160a01b0381166000908152600b602052604090205460ff16611f885760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881b9bdd081c9959da5cdd195c995960621b60448201526064016107f3565b6001600160a01b0381166000908152600b60209081526040808320805460ff191690556008825280832083905560099091528120819055600c54905b8181101561200e57826001600160a01b03166000600c018281548110611fec57611fec61393c565b6000918252602090912001546001600160a01b03161461200e57600101611fc4565b81811461087f57600182111561209657600c61202b6001846138cd565b8154811061203b5761203b61393c565b600091825260209091200154600c80546001600160a01b0390921691839081106120675761206761393c565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b600c8054806120a7576120a7613952565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6002600d54036121425760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107f3565b6002600d55565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b179052905160009182916001600160a01b0385169161218c91613968565b600060405180830381855afa9150503d80600081146121c7576040519150601f19603f3d011682016040523d82523d6000602084013e6121cc565b606091505b50915050808060200190518101906121e49190613994565b9392505050565b6000806121f784612d8b565b905061220584333086612e37565b8061220f85612d8b565b61221991906138cd565b949350505050565b60006122308460000151611327565b61224c5760405162461bcd60e51b81526004016107f390613910565b60a08401516122a95760405162461bcd60e51b8152602060048201526024808201527f746172676574526563697069656e742063616e6e6f74206265206279746573336044820152633228302960e01b60648201526084016107f3565b60006122bd85604001518660200151610ac3565b90506000811161230f5760405162461bcd60e51b815260206004820152601d60248201527f6e6f726d616c697a656420616d6f756e74206d757374206265203e203000000060448201526064016107f3565b600061232386606001518760200151610ac3565b90508560600151600014806123385750600081115b6123845760405162461bcd60e51b815260206004820152601b60248201527f696e76616c696420746f4e6174697665546f6b656e416d6f756e74000000000060448201526064016107f3565b608086015161ffff16600090815260076020526040902054806123e15760405162461bcd60e51b81526020600482015260156024820152741d185c99d95d081b9bdd081c9959da5cdd195c9959605a1b60448201526064016107f3565b60006124076123fd89608001518a600001518b60200151611274565b8960200151610ac3565b905061241383826138fd565b84116124575760405162461bcd60e51b81526020600482015260136024820152721a5b9cdd59999a58da595b9d08185b5bdd5b9d606a1b60448201526064016107f3565b600061248a6040518060800160405280600160ff1681526020018481526020018681526020018b60a00151815250611988565b905060006124a06004546001600160a01b031690565b90506124b58a60000151828c60400151612e6f565b806001600160a01b031663c5a5ebda898c600001518d604001518e60800151898f896040518863ffffffff1660e01b81526004016124f8969594939291906139b1565b60206040518083038185885af1158015612516573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610d6d9190613a17565b60006125488260206138fd565b835110156125905760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b60448201526064016107f3565b50016020015190565b60006125a68260026138fd565b835110156125ed5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b60448201526064016107f3565b50016002015190565b60006001600160a01b03198216156126465760405162461bcd60e51b8152602060048201526013602482015272696e76616c69642045564d206164647265737360681b60448201526064016107f3565b5090565b606060008060006126636003546001600160a01b031690565b6001600160a01b031663a9e11893866040518263ffffffff1660e01b815260040161268e9190613665565b600060405180830381865afa1580156126ab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126d39190810190613b56565b905060006126e48260e00151610d7b565b90506126ef81611327565b6127325760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881b9bdd081c9959da5cdd195c995960621b60448201526064016107f3565b600061273d82612d8b565b905060006127536004546001600160a01b031690565b90506000816001600160a01b031663c3f511c18a6040518263ffffffff1660e01b81526004016127839190613665565b6000604051808303816000875af11580156127a2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127ca9190810190613c7a565b90506000836127d886612d8b565b6127e291906138cd565b90506000836001600160a01b031663ea63738d846040518263ffffffff1660e01b81526004016128129190613665565b600060405180830381865afa15801561282f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128579190810190613cae565b9050612877876060015161ffff1660009081526007602052604090205490565b8160c00151146128c95760405162461bcd60e51b815260206004820152601760248201527f636f6e7472616374206e6f74207265676973746572656400000000000000000060448201526064016107f3565b8660a001516001600160401b03168760800151886060015161ffff167fcaf280c8cfeba144da67230d9b009c8f868a75bac9a528fa0474be1ba317c16960405160405180910390a460e001519a9099509397509295505050505050565b34156129805760405162461bcd60e51b815260206004820152602360248201527f726563697069656e742063616e6e6f742073776170206e61746976652061737360448201526265747360e81b60648201526084016107f3565b6000546001600160a01b0363010000009091048116908516811480156129a35750815b15612a3e57604051632e1a7d4d60e01b8152600481018490526001600160a01b03821690632e1a7d4d90602401600060405180830381600087803b1580156129ea57600080fd5b505af11580156129fe573d6000803e3d6000fd5b50506040516001600160a01b038716925085156108fc02915085906000818181858888f19350505050158015612a38573d6000803e3d6000fd5b50612a49565b612a49858585612ba8565b5050505050565b3415612a935760405162461bcd60e51b815260206004820152601260248201527176616c7565206d757374206265207a65726f60701b60448201526064016107f3565b8015612b7957600054604051632e1a7d4d60e01b81526004810186905263010000009091046001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015612ae557600080fd5b505af1158015612af9573d6000803e3d6000fd5b50505050826001600160a01b03166108fc8386612b1691906138cd565b6040518115909202916000818181858888f19350505050158015612b3e573d6000803e3d6000fd5b508115612b7457604051339083156108fc029084906000818181858888f19350505050158015612b72573d6000803e3d6000fd5b505b611f23565b600054630100000090046001600160a01b0316612b9b818561126386896138cd565b8215612a4957612a498133855b6040516001600160a01b03831660248201526044810182905261087f90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612f84565b6000612c188260016138fd565b83511015612c5e5760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b60448201526064016107f3565b50016001015190565b6000612c748260206138fd565b835110156125905760405162461bcd60e51b8152602060048201526015602482015274746f55696e743235365f6f75744f66426f756e647360581b60448201526064016107f3565b6001600160a01b0381166000908152600b602052604090205460ff1615612d255760405162461bcd60e51b815260206004820152601860248201527f746f6b656e20616c72656164792072656769737465726564000000000000000060448201526064016107f3565b6001600160a01b03166000818152600b60205260408120805460ff19166001908117909155600c805491820181559091527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b0319169091179055565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b179052905160009182916001600160a01b03851691612ddf91613968565b600060405180830381855afa9150503d8060008114612e1a576040519150601f19603f3d011682016040523d82523d6000602084013e612e1f565b606091505b50915050808060200190518101906121e49190613759565b6040516001600160a01b0380851660248301528316604482015260648101829052611f239085906323b872dd60e01b90608401612bd4565b801580612ee95750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015612ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ee79190613759565b155b612f545760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016107f3565b6040516001600160a01b03831660248201526044810182905261087f90849063095ea7b360e01b90606401612bd4565b6000612fd9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130569092919063ffffffff16565b80519091501561087f5780806020019051810190612ff79190613d76565b61087f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016107f3565b6060612219848460008585600080866001600160a01b0316858760405161307d9190613968565b60006040518083038185875af1925050503d80600081146130ba576040519150601f19603f3d011682016040523d82523d6000602084013e6130bf565b606091505b50915091506130d0878383876130db565b979650505050505050565b6060831561314a578251600003613143576001600160a01b0385163b6131435760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107f3565b5081612219565b612219838381511561315f5781518083602001fd5b8060405162461bcd60e51b81526004016107f39190613665565b61ffff8116811461318957600080fd5b50565b6001600160a01b038116811461318957600080fd5b600080604083850312156131b457600080fd5b82356131bf81613179565b915060208301356131cf8161318c565b809150509250929050565b63ffffffff8116811461318957600080fd5b60008060008060008060c0878903121561320557600080fd5b86356132108161318c565b95506020870135945060408701359350606087013561322e81613179565b92506080870135915060a0870135613245816131da565b809150509295509295509295565b60ff8116811461318957600080fd5b6000806040838503121561327557600080fd5b8235915060208301356131cf81613253565b6000806000806080858703121561329d57600080fd5b8435935060208501356132af81613179565b92506040850135915060608501356132c6816131da565b939692955090935050565b6000602082840312156132e357600080fd5b81356121e48161318c565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613326576133266132ee565b60405290565b60405161016081016001600160401b0381118282101715613326576133266132ee565b60405161010081016001600160401b0381118282101715613326576133266132ee565b604051601f8201601f191681016001600160401b038111828210171561339a5761339a6132ee565b604052919050565b60006001600160401b038211156133bb576133bb6132ee565b50601f01601f191660200190565b6000602082840312156133db57600080fd5b81356001600160401b038111156133f157600080fd5b8201601f8101841361340257600080fd5b8035613415613410826133a2565b613372565b81815285602083850101111561342a57600080fd5b81602084016020830137600091810160200191909152949350505050565b6000806040838503121561345b57600080fd5b823561346681613179565b946020939093013593505050565b6000806020838503121561348757600080fd5b82356001600160401b038082111561349e57600080fd5b818501915085601f8301126134b257600080fd5b8135818111156134c157600080fd5b8660208285010111156134d357600080fd5b60209290920196919550909350505050565b6000806000606084860312156134fa57600080fd5b833561350581613179565b925060208401356135158161318c565b9150604084013561352581613253565b809150509250925092565b60006020828403121561354257600080fd5b81356121e481613179565b801515811461318957600080fd5b6000806040838503121561356e57600080fd5b823561357981613179565b915060208301356131cf8161354d565b6000806040838503121561359c57600080fd5b82356134668161318c565b6000608082840312156135b957600080fd5b604051608081018181106001600160401b03821117156135db576135db6132ee565b60405282356135e981613253565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b60005b83811015613630578181015183820152602001613618565b50506000910152565b60008151808452613651816020860160208601613615565b601f01601f19169290920160200192915050565b6020815260006121e46020830184613639565b6020808252825182820181905260009190848201906040850190845b818110156136b95783516001600160a01b031683529284019291840191600101613694565b50909695505050505050565b6000806000606084860312156136da57600080fd5b83356136e581613179565b925060208401356136f58161318c565b929592945050506040919091013590565b60208082526014908201527331b0b63632b9103737ba103a34329037bbb732b960611b604082015260600190565b6020808252600b908201526a3bb937b7339031b430b4b760a91b604082015260600190565b60006020828403121561376b57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60ff8281168282160390811115610af757610af7613772565b600181815b808511156137dc5781600019048211156137c2576137c2613772565b808516156137cf57918102915b93841c93908002906137a6565b509250929050565b6000826137f357506001610af7565b8161380057506000610af7565b816001811461381657600281146138205761383c565b6001915050610af7565b60ff84111561383157613831613772565b50506001821b610af7565b5060208310610133831016604e8410600b841016171561385f575081810a610af7565b61386983836137a1565b806000190482111561387d5761387d613772565b029392505050565b60006121e460ff8416836137e4565b6000826138b157634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610af757610af7613772565b81810381811115610af757610af7613772565b6000602082840312156138f257600080fd5b81516121e48161318c565b80820180821115610af757610af7613772565b6020808252601290820152711d1bdad95b881b9bdd081858d8d95c1d195960721b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b6000825161397a818460208701613615565b9190910192915050565b805161398f81613253565b919050565b6000602082840312156139a657600080fd5b81516121e481613253565b60018060a01b038716815285602082015261ffff8516604082015283606082015263ffffffff8316608082015260c060a082015260006139f460c0830184613639565b98975050505050505050565b80516001600160401b038116811461398f57600080fd5b600060208284031215613a2957600080fd5b6121e482613a00565b805161398f816131da565b805161398f81613179565b600082601f830112613a5957600080fd5b8151613a67613410826133a2565b818152846020838601011115613a7c57600080fd5b612219826020830160208701613615565b600082601f830112613a9e57600080fd5b815160206001600160401b03821115613ab957613ab96132ee565b613ac7818360051b01613372565b82815260079290921b84018101918181019086841115613ae657600080fd5b8286015b84811015613b4b5760808189031215613b035760008081fd5b613b0b613304565b815181528482015185820152604080830151613b2681613253565b90820152606082810151613b3981613253565b90820152835291830191608001613aea565b509695505050505050565b600060208284031215613b6857600080fd5b81516001600160401b0380821115613b7f57600080fd5b908301906101608286031215613b9457600080fd5b613b9c61332c565b613ba583613984565b8152613bb360208401613a32565b6020820152613bc460408401613a32565b6040820152613bd560608401613a3d565b606082015260808301516080820152613bf060a08401613a00565b60a0820152613c0160c08401613984565b60c082015260e083015182811115613c1857600080fd5b613c2487828601613a48565b60e083015250610100613c38818501613a32565b908201526101208381015183811115613c5057600080fd5b613c5c88828701613a8d565b91830191909152506101409283015192810192909252509392505050565b600060208284031215613c8c57600080fd5b81516001600160401b03811115613ca257600080fd5b61221984828501613a48565b600060208284031215613cc057600080fd5b81516001600160401b0380821115613cd757600080fd5b908301906101008286031215613cec57600080fd5b613cf461334f565b613cfd83613984565b81526020830151602082015260408301516040820152613d1f60608401613a3d565b606082015260808301516080820152613d3a60a08401613a3d565b60a082015260c083015160c082015260e083015182811115613d5b57600080fd5b613d6787828601613a48565b60e08301525095945050505050565b600060208284031215613d8857600080fd5b81516121e48161354d56fea2646970667358221220043ecf0d1429bfc7866a5607e98ae2b1cca0eeef46c7279047c0211efe0f076764736f6c63430008110033000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000a321448d90d4e5b0a732867c18ea198e75cac48e000000000000000000000000796dff6d74f3e27060b71255fe517bfb23c93eed000000000000000000000000471ece3750da237f93b8e339c536989b8978a4380000000000000000000000000000000000000000000000000000000000000000

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

000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000a321448d90d4e5b0a732867c18ea198e75cac48e000000000000000000000000796dff6d74f3e27060b71255fe517bfb23c93eed000000000000000000000000471ece3750da237f93b8e339c536989b8978a4380000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : chainId (uint16): 14
Arg [1] : wormhole (address): 0xa321448d90d4e5b0a732867c18ea198e75cac48e
Arg [2] : tokenBridge_ (address): 0x796dff6d74f3e27060b71255fe517bfb23c93eed
Arg [3] : wethAddress (address): 0x471ece3750da237f93b8e339c536989b8978a438
Arg [4] : unwrapWeth_ (bool): False

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [1] : 000000000000000000000000a321448d90d4e5b0a732867c18ea198e75cac48e
Arg [2] : 000000000000000000000000796dff6d74f3e27060b71255fe517bfb23c93eed
Arg [3] : 000000000000000000000000471ece3750da237f93b8e339c536989b8978a438
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000


Deployed ByteCode Sourcemap

632:26699:9:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4250:222:11;;;;;;;;;;-1:-1:-1;4250:222:11;;;;;:::i;:::-;;:::i;:::-;;1612:496;;;;;;;;;;;;;:::i;3553:1500:9:-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1688:31:16;;;1670:50;;1658:2;1643:18;3553:1500:9;;;;;;;;1279:107:10;;;;;;;;;;-1:-1:-1;1355:24:10;;1279:107;;;1877:25:16;;;1865:2;1850:18;1279:107:10;1731:177:16;2520:221:10;;;;;;;;;;-1:-1:-1;2520:221:10;;;;;:::i;:::-;;:::i;2747:223::-;;;;;;;;;;-1:-1:-1;2747:223:10;;;;;:::i;:::-;;:::i;5851:1563:9:-;;;;;;:::i;:::-;;:::i;2023:110:10:-;;;;;;;;;;-1:-1:-1;2023:110:10;;;;;:::i;:::-;-1:-1:-1;;;;;2103:23:10;2077:7;2103:23;;;:16;:23;;;;;;;2023:110;22584:811:9;;;;;;;;;;-1:-1:-1;22584:811:9;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;5347:32:16;;;5329:51;;5317:2;5302:18;22584:811:9;5183:203:16;6738:268:11;;;;;;;;;;-1:-1:-1;6738:268:11;;;;;:::i;:::-;;:::i;1886:131:10:-;;;;;;;;;;-1:-1:-1;1886:131:10;;;;;:::i;:::-;-1:-1:-1;;;;;1977:33:10;1951:7;1977:33;;;:26;:33;;;;;;;1886:131;12181:5092:9;;;;;;:::i;:::-;;:::i;26092:471::-;;;;;;;;;;-1:-1:-1;26092:471:9;;;;;:::i;:::-;;:::i;1392:119:10:-;;;;;;;;;;-1:-1:-1;1392:119:10;;;;;:::i;:::-;;:::i;:::-;;;6998:14:16;;6991:22;6973:41;;6961:2;6946:18;1392:119:10;6833:187:16;1123:150:10;;;;;;;;;;-1:-1:-1;1123:150:10;;;;;:::i;:::-;1224:42;;1198:7;1224:42;;;:26;:42;;;;;;;1123:150;1644:111;;;;;;;;;;-1:-1:-1;1722:26:10;;1644:111;;3075:530:11;;;;;;;;;;-1:-1:-1;3075:530:11;;;;;:::i;:::-;;:::i;4882:328::-;;;;;;;;;;-1:-1:-1;4882:328:11;;;;;:::i;:::-;;:::i;1761:119:10:-;;;;;;;;;;-1:-1:-1;1761:119:10;;;;;:::i;:::-;1845:28;;1819:7;1845:28;;;:18;:28;;;;;;;1761:119;1174:801:12;;;;;;;;;;-1:-1:-1;1174:801:12;;;;;:::i;:::-;;:::i;:::-;;;;;;8014:13:16;;8029:4;8010:24;7992:43;;8091:4;8079:17;;;8073:24;8051:20;;;8044:54;8154:4;8142:17;;;8136:24;8114:20;;;8107:54;8217:4;8205:17;;;8199:24;8177:20;;;8170:54;;;;7979:3;7964:19;;7775:455;2629:178:11;;;;;;;;;;-1:-1:-1;2629:178:11;;;;;:::i;:::-;;:::i;599:102:10:-;;;;;;;;;;-1:-1:-1;678:15:10;;-1:-1:-1;;;;;678:15:10;599:102;;407:83;;;;;;;;;;-1:-1:-1;471:12:10;;-1:-1:-1;;;;;471:12:10;407:83;;24964:737:9;;;;;;;;;;-1:-1:-1;24964:737:9;;;;;:::i;:::-;;:::i;5392:278:11:-;;;;;;;;;;-1:-1:-1;5392:278:11;;;;;:::i;:::-;;:::i;774:261::-;;;;;;;;;;-1:-1:-1;774:261:11;;;;;:::i;:::-;;:::i;1031:86:10:-;;;;;;;;;;-1:-1:-1;1071:6:10;1096:14;1031:86;;1096:14;;;;9433:38:16;;9421:2;9406:18;1031:86:10;9289:188:16;935:90:10;;;;;;;;;;-1:-1:-1;978:4:10;1001:17;;;;;;935:90;;451:391:12;;;;;;;;;;-1:-1:-1;451:391:12;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1183:159:11:-;;;;;;;;;;-1:-1:-1;1183:159:11;;;;;:::i;:::-;;:::i;836:93:10:-;;;;;;;;;;-1:-1:-1;873:5:10;903:18;;;;-1:-1:-1;;;;;903:18:10;836:93;;2139:375;;;;;;;;;;-1:-1:-1;2139:375:10;;;;;:::i;:::-;;:::i;707:123::-;;;;;;;;;;-1:-1:-1;803:18:10;;-1:-1:-1;;;;;803:18:10;707:123;;3769:217:11;;;;;;;;;;-1:-1:-1;3769:217:11;;;;;:::i;:::-;;:::i;23838:705:9:-;;;;;;;;;;-1:-1:-1;23838:705:9;;;;;:::i;:::-;;:::i;1517:121:10:-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;496:97::-;;;;;;;;;;-1:-1:-1;567:19:10;;-1:-1:-1;;;;;567:19:10;496:97;;6197:365:11;;;;;;;;;;-1:-1:-1;6197:365:11;;;;;:::i;:::-;;:::i;7315:281::-;;;;;;;;;;-1:-1:-1;7315:281:11;;;;;:::i;:::-;;:::i;4250:222::-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;;;;;;;;;4363:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;4391:19:11;::::2;4383:45;;;::::0;-1:-1:-1;;;4383:45:11;;13416:2:16;4383:45:11::2;::::0;::::2;13398:21:16::0;13455:2;13435:18;;;13428:30;-1:-1:-1;;;13474:18:16;;;13467:43;13527:18;;4383:45:11::2;13214:337:16::0;4383:45:11::2;4439:26;4459:5;4439:19;:26::i;:::-;7697:1:::1;4250:222:::0;;:::o;1612:496::-;1711:16;1730:14;567:19:10;;-1:-1:-1;;;;;567:19:10;;496:97;1730:14:11;1711:33;-1:-1:-1;1763:10:11;-1:-1:-1;;;;;1763:22:11;;;1755:62;;;;-1:-1:-1;;;1755:62:11;;13758:2:16;1755:62:11;;;13740:21:16;13797:2;13777:18;;;13770:30;13836:29;13816:18;;;13809:57;13883:18;;1755:62:11;13556:351:16;1755:62:11;1868:20;1891:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;1891:7:11;234:12:13;:21;;-1:-1:-1;;;;;;234:21:13;-1:-1:-1;;;;;234:21:13;;;;;1868:30:11;-1:-1:-1;2015:27:11;2039:1;2015:15;:27::i;:::-;2092:8;-1:-1:-1;;;;;2058:43:11;2078:12;-1:-1:-1;;;;;2058:43:11;;;;;;;;;;;1662:446;;1612:496::o;3553:1500:9:-;3798:22;2261:21:0;:19;:21::i;:::-;3959:19:9::1;3981:10;678:15:10::0;;-1:-1:-1;;;;;678:15:10;;599:102;3981:10:9::1;-1:-1:-1::0;;;;;3981:21:9::1;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3959:45;;4035:11;4022:9;:24;4014:55;;;::::0;-1:-1:-1;;;4014:55:9;;14303:2:16;4014:55:9::1;::::0;::::1;14285:21:16::0;14342:2;14322:18;;;14315:30;-1:-1:-1;;;14361:18:16;;;14354:48;14419:18;;4014:55:9::1;14101:342:16::0;4014:55:9::1;4232:19;4254:18;4266:5;4254:11;:18::i;:::-;4232:40;;4291:106;4322:38;4338:6;4346:13;4322:15;:38::i;:::-;4374:13;4291:17;:106::i;:::-;4282:115;;4536:28;4550:5;4557:6;4536:13;:28::i;:::-;4527:37;;4656:390;4694:296;;;;;;;;4742:5;-1:-1:-1::0;;;;;4694:296:9::1;;;;;4812:13;4694:296;;;;;;4773:6;4694:296;;;;4864:19;4694:296;;;;4914:11;4694:296;;;;;;4960:15;4694:296;;::::0;5004:7:::1;5025:11;4656:24;:390::i;:::-;4638:408;;3822:1231;;2303:20:0::0;1716:1;2809:7;:22;2629:209;2303:20;3553:1500:9;;;;;;;;:::o;2520:221:10:-;2620:7;2654:1;2643:8;:12;;;2639:73;;;2688:12;2699:1;2688:8;:12;:::i;:::-;2681:20;;:2;:20;:::i;:::-;2671:30;;;;:::i;:::-;;;2639:73;-1:-1:-1;2728:6:10;2520:221;;;;;:::o;2747:223::-;2849:7;2883:1;2872:8;:12;;;2868:73;;;2917:12;2928:1;2917:8;:12;:::i;:::-;2910:20;;:2;:20;:::i;:::-;2900:30;;;;:::i;5851:1563:9:-;6040:22;1001:17:10;;;;;;;6074:57:9;;;;-1:-1:-1;;;6074:57:9;;16716:2:16;6074:57:9;;;16698:21:16;;;16735:18;;;16728:30;16794:34;16774:18;;;16767:62;16846:18;;6074:57:9;16514:356:16;6074:57:9;6269:19;6291:10;678:15:10;;-1:-1:-1;;;;;678:15:10;;599:102;6291:10:9;-1:-1:-1;;;;;6291:21:9;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6269:45;;6344:11;6332:9;:23;6324:54;;;;-1:-1:-1;;;6324:54:9;;14303:2:16;6324:54:9;;;14285:21:16;14342:2;14322:18;;;14315:30;-1:-1:-1;;;14361:18:16;;;14354:48;14419:18;;6324:54:9;14101:342:16;6324:54:9;6449:14;6466:23;6478:11;6466:9;:23;:::i;:::-;6449:40;;6523:12;6547:50;6565:27;6581:6;6589:2;6565:15;:27::i;:::-;6594:2;6547:17;:50::i;:::-;6538:59;;:6;:59;:::i;:::-;6523:74;-1:-1:-1;6611:8:9;;6607:73;;6635:34;;6643:10;;6635:34;;;;;6664:4;;6635:34;;;;6664:4;6643:10;6635:34;;;;;;;;;;;;;;;;;;;;;6607:73;6740:22;6765:13;6774:4;6765:6;:13;:::i;:::-;6740:38;;6788:10;6801:6;873:5:10;903:18;-1:-1:-1;;;;;903:18:10;;;;;;836:93;6801:6:9;6788:19;;6860:4;-1:-1:-1;;;;;6860:12:9;;6894:14;6860:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7012:395;7050:301;;;;;;;;7106:4;-1:-1:-1;;;;;7050:301:9;;;;;7144:2;7050:301;;;;;;7172:14;7050:301;;;;7225:19;7050:301;;;;7275:11;7050:301;;;;;;7321:15;7050:301;;;7365:7;7386:11;7012:24;:395::i;:::-;6994:413;5851:1563;-1:-1:-1;;;;;;;;;;5851:1563:9:o;22584:811::-;22687:20;;22797:21;:7;22815:2;22797:17;:21::i;:::-;22773:45;-1:-1:-1;22828:17:9;22848:20;:7;22865:2;22848:16;:20::i;:::-;22828:40;;23004:9;1071:6:10;1096:14;;;;1031:86;23004:9:9;22990:23;;:10;:23;;;22986:403;;803:18:10;;-1:-1:-1;;;;;803:18:10;23098:53:9;;-1:-1:-1;;;23098:53:9;;17210:6:16;17198:19;;23098:53:9;;;17180:38:16;17234:18;;;17227:34;;;-1:-1:-1;;;;;23098:26:9;;;;;;;17153:18:16;;23098:53:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23083:68;-1:-1:-1;;;;;;23173:26:9;;23165:57;;;;-1:-1:-1;;;23165:57:9;;17730:2:16;23165:57:9;;;17712:21:16;17769:2;17749:18;;;17742:30;-1:-1:-1;;;17788:18:16;;;17781:48;17846:18;;23165:57:9;17528:342:16;23165:57:9;22986:403;;;23347:31;23364:13;23347:16;:31::i;:::-;23332:46;;22986:403;22709:686;;22584:811;;;:::o;6738:268:11:-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;6872:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;6921:1:::2;6900:18;:22;6892:56;;;::::0;-1:-1:-1;;;6892:56:11;;18077:2:16;6892:56:11::2;::::0;::::2;18059:21:16::0;18116:2;18096:18;;;18089:30;-1:-1:-1;;;18135:18:16;;;18128:51;18196:18;;6892:56:11::2;17875:345:16::0;6892:56:11::2;6959:40;6980:18;1121:24:13::0;:36;1053:111;12181:5092:9;12342:20;12364:14;12380:13;12410:41;12428:22;;12410:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12410:17:9;;-1:-1:-1;;;12410:41:9:i;:::-;12341:110;;;;;;12527:42;12572:54;12609:7;12572:23;:54::i;:::-;12527:99;;12697:17;12717:51;12734:17;:33;;;12717:16;:51::i;:::-;12697:71;;12778:15;12796:12;978:4:10;1001:17;;;;;;;;935:90;12796:12:9;12778:30;-1:-1:-1;;;;;;12858:23:9;;:10;:23;12854:238;;12897:139;12938:5;12961:9;12988:6;13012:10;12897:23;:139::i;:::-;13075:7;;;;;;12181:5092;;:::o;12854:238::-;13134:19;13156:18;13168:5;13156:11;:18::i;:::-;13134:40;;13268:102;13299:17;:34;;;13347:13;13268:17;:102::i;:::-;13231:34;;;:139;873:5:10;903:18;;;;-1:-1:-1;;;;;903:18:10;-1:-1:-1;;;;;13420:24:9;:5;-1:-1:-1;;;;;13420:24:9;;13416:266;;13460:166;13499:6;13523:9;13550:17;:34;;;13602:10;13460:21;:166::i;:::-;13665:7;;;;;;;12181:5092;;:::o;13416:266::-;13748:37;;;;:41;13744:2913;;13896:117;13931:17;:37;;;13986:13;13896:17;:117::i;:::-;13856:37;;;:157;14434:32;;14509:31;14534:5;14509:24;:31::i;:::-;14480:60;;14598:18;14558:17;:37;;;:58;14554:155;;;14636:37;;;:58;;;14554:155;14816:120;14862:5;14885:17;:37;;;14816:28;:120::i;:::-;14789:147;-1:-1:-1;15335:28:9;;15331:1316;;15490:24;15477:9;:37;;15448:140;;;;-1:-1:-1;;;15448:140:9;;18427:2:16;15448:140:9;;;18409:21:16;;;18446:18;;;18439:30;18505:34;18485:18;;;18478:62;18557:18;;15448:140:9;18225:356:16;15448:140:9;15678:21;15702:36;15714:24;15702:9;:36;:::i;:::-;15678:60;-1:-1:-1;15760:17:9;;15756:107;;15801:43;;15809:10;;15801:43;;;;;15830:13;;15801:43;;;;15830:13;15809:10;15801:43;;;;;;;;;;;;;;;;;;;;;15756:107;15948:53;;-1:-1:-1;;;;;15948:27:9;;;:53;;;;;15976:24;;15948:53;;;;15976:24;15948:27;:53;;;;;;;;;;;;;;;;;;;;;16157:5;-1:-1:-1;;;;;16060:225:9;16125:10;-1:-1:-1;;;;;16060:225:9;16094:9;-1:-1:-1;;;;;16060:225:9;;16184:17;:37;;;16243:24;16060:225;;;;;;18760:25:16;;;18816:2;18801:18;;18794:34;18748:2;18733:18;;18586:248;16060:225:9;;;;;;;;15365:935;15331:1316;;;16437:1;16397:37;;;:41;16538:9;:13;16534:99;;16575:39;;16583:10;;16604:9;16575:39;;;;;;;;;16604:9;16583:10;16575:39;;;;;;;;;;;;;;;;;;;;;16534:99;13791:2866;;13744:2913;16723:24;16799:17;:37;;;16762:17;:34;;;:74;;;;:::i;:::-;16723:113;-1:-1:-1;16902:20:9;;16898:180;;16938:129;16985:5;17009:10;17037:16;16938:22;:129::i;:::-;17145:121;17188:5;17208:9;17231:25;17240:16;17231:6;:25;:::i;:::-;17145:22;:121::i;:::-;12270:5003;;;;;;;;12181:5092;;:::o;26092:471::-;-1:-1:-1;;;;;2103:23:10;;26225:30:9;2103:23:10;;;:16;:23;;;;;;26351:13:9;26368:1;26351:18;26343:48;;;;-1:-1:-1;;;26343:48:9;;19171:2:16;26343:48:9;;;19153:21:16;19210:2;19190:18;;;19183:30;-1:-1:-1;;;19229:18:16;;;19222:47;19286:18;;26343:48:9;18969:341:16;26343:48:9;1722:26:10;;26518:37:9;;:13;:37;:::i;:::-;1355:24:10;;1845:28;;;1819:7;1845:28;;;:18;:28;;;;;;26438:14:9;26444:8;26438:2;:14;:::i;:::-;:42;;;;:::i;:::-;:64;;;;:::i;:::-;:118;;;;:::i;:::-;26401:155;26092:471;-1:-1:-1;;;;;26092:471:9:o;1392:119:10:-;-1:-1:-1;;;;;1476:28:10;1453:4;1476:28;;;:21;:28;;;;;;;;;1392:119::o;3075:530:11:-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;3258:15;3237:115:::1;;;::::0;-1:-1:-1;;;3237:115:11;;19517:2:16;3237:115:11::1;::::0;::::1;19499:21:16::0;19556:2;19536:18;;;19529:30;19595:34;19575:18;;;19568:62;-1:-1:-1;;;19646:18:16;;;19639:37;19693:19;;3237:115:11::1;19315:403:16::0;3237:115:11::1;3383:13;::::0;::::1;::::0;;::::1;::::0;:38:::1;;-1:-1:-1::0;1071:6:10;1096:14;;3400:21:11;;::::1;1096:14:10::0;;3400:21:11::1;;3383:38;3362:124;;;::::0;-1:-1:-1;;;3362:124:11;;19925:2:16;3362:124:11::1;::::0;::::1;19907:21:16::0;19964:2;19944:18;;;19937:30;20003:34;19983:18;;;19976:62;-1:-1:-1;;;20054:18:16;;;20047:37;20101:19;;3362:124:11::1;19723:403:16::0;3362:124:11::1;992:36:13::0;;;;;:6;:36;;;:26;:36;;;;;:48;3075:530:11:o;3554:44::-:1;3075:530:::0;;:::o;4882:328::-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;1071:6:10;1096:14;;;4998:21:11::1;;:8;:21;;::::0;4990:47:::1;;;::::0;-1:-1:-1;;;4990:47:11;;20333:2:16;4990:47:11::1;::::0;::::1;20315:21:16::0;20372:2;20352:18;;;20345:30;-1:-1:-1;;;20391:18:16;;;20384:43;20444:18;;4990:47:11::1;20131:337:16::0;4990:47:11::1;1224:42:10::0;;;5111:1:11::1;1224:42:10::0;;;:26;:42;;;;;;5047:114:11::1;;;::::0;-1:-1:-1;;;5047:114:11;;20675:2:16;5047:114:11::1;::::0;::::1;20657:21:16::0;20714:2;20694:18;;;20687:30;-1:-1:-1;;;20733:18:16;;;20726:52;20795:18;;5047:114:11::1;20473:346:16::0;5047:114:11::1;2685:28:13::0;;;;;:6;:28;;;:18;:28;;;;;:34;3075:530:11:o;1174:801:12:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1389:22:12;:7;-1:-1:-1;1389:15:12;:22::i;:::-;1368:43;;;;1421:10;1430:1;1421:10;;:::i;:::-;;;1450:8;:18;;;:23;;1472:1;1450:23;1442:53;;;;-1:-1:-1;;;1442:53:12;;21026:2:16;1442:53:12;;;21008:21:16;21065:2;21045:18;;;21038:30;-1:-1:-1;;;21084:18:16;;;21077:47;21141:18;;1442:53:12;20824:341:16;1442:53:12;1564:24;:7;1582:5;1564:17;:24::i;:::-;1536:25;;;;:52;;;;1598:11;;;;:::i;:::-;;-1:-1:-1;1707:24:12;:7;1598:11;1707:17;:24::i;:::-;1676:28;;;:55;1741:11;1750:2;1741:11;;:::i;:::-;;-1:-1:-1;1854:24:12;:7;1741:11;1854:17;:24::i;:::-;1827;;;:51;1888:11;1897:2;1888:11;;:::i;:::-;;;1927:7;:14;1918:5;:23;1910:58;;;;-1:-1:-1;;;1910:58:12;;21372:2:16;1910:58:12;;;21354:21:16;21411:2;21391:18;;;21384:30;-1:-1:-1;;;21430:18:16;;;21423:52;21492:18;;1910:58:12;21170:346:16;1910:58:12;1299:676;1174:801;;;:::o;2629:178:11:-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;2750:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;675:6:13::0;:31;;-1:-1:-1;;675:31:13;;;;;;;;;7697:1:11::1;4250:222:::0;;:::o;24964:737:9:-;25084:20;25177:19;25199:18;25211:5;25199:11;:18::i;:::-;25177:40;;25227:20;25250:28;25270:6;873:5:10;903:18;-1:-1:-1;;;;;903:18:10;;;;;;836:93;25270:6:9;25250:11;:28::i;:::-;25227:51;;25309:14;25293:30;;:13;:30;;;25289:406;;;25457:30;25473:14;25457:13;:30;:::i;:::-;25450:38;;:2;:38;:::i;:::-;25426:21;25441:5;25426:14;:21::i;:::-;:62;;;;:::i;:::-;25392:14;25370:19;1355:24:10;;;1279:107;25370:19:9;:36;;;;:::i;:::-;:119;;;;:::i;:::-;25339:150;;25289:406;;;25663:21;25678:5;25663:14;:21::i;:::-;25613:30;25630:13;25613:14;:30;:::i;:::-;25606:38;;:2;:38;:::i;:::-;25573:14;25551:19;1355:24:10;;;1279:107;25551:19:9;:36;;;;:::i;:::-;:93;;;;:::i;:::-;:133;;;;:::i;:::-;25520:164;;25289:406;25106:595;;24964:737;;;;:::o;5392:278:11:-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;5530:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;5581:1:::2;5558:20;:24;5550:58;;;::::0;-1:-1:-1;;;5550:58:11;;18077:2:16;5550:58:11::2;::::0;::::2;18059:21:16::0;18116:2;18096:18;;;18089:30;-1:-1:-1;;;18135:18:16;;;18128:51;18196:18;;5550:58:11::2;17875:345:16::0;5550:58:11::2;5619:44;5642:20;1240:26:13::0;:38;1170:115;774:261:11;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;905:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;933:22:11;::::2;925:67;;;::::0;-1:-1:-1;;;925:67:11;;21723:2:16;925:67:11::2;::::0;::::2;21705:21:16::0;;;21742:18;;;21735:30;21801:34;21781:18;;;21774:62;21853:18;;925:67:11::2;21521:356:16::0;925:67:11::2;1003:25;1019:8;1003:15;:25::i;451:391:12:-:0;554:20;593:8;:18;;;:23;;615:1;593:23;585:53;;;;-1:-1:-1;;;585:53:12;;21026:2:16;585:53:12;;;21008:21:16;21065:2;21045:18;;;21038:30;-1:-1:-1;;;21084:18:16;;;21077:47;21141:18;;585:53:12;20824:341:16;585:53:12;688:18;;720:25;;;;;759:28;;;;;801:24;;;;658:177;;;;688:18;759:28;;801:24;658:177;22129:3:16;22107:16;;;;-1:-1:-1;;;;;;22103:36:16;22091:49;;22165:1;22156:11;;22149:27;;;;22201:2;22192:12;;22185:28;22238:2;22229:12;;22222:28;22275:2;22266:12;;21882:402;658:177:12;;;;;;;;;;;;;648:187;;451:391;;;:::o;1183:159:11:-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;1288:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;1308:27:::2;1332:1;1308:15;:27::i;2139:375:10:-:0;2199:7;2253:18;;-1:-1:-1;;;;;2253:18:10;;;;;;2103:23;;:16;:23;;;;;;;;;;;;;;;2371:1;2353:15;:19;:40;;;;;2392:1;2376:13;:17;2353:40;2332:104;;;;-1:-1:-1;;;2332:104:10;;19171:2:16;2332:104:10;;;19153:21:16;19210:2;19190:18;;;19183:30;-1:-1:-1;;;19229:18:16;;;19222:47;19286:18;;2332:104:10;18969:341:16;2332:104:10;2494:13;2476:15;2454:19;1355:24;;;1279:107;2454:19;:37;;;;:::i;:::-;:53;;;;:::i;3769:217:11:-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;3880:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;3908:19:11;::::2;3900:45;;;::::0;-1:-1:-1;;;3900:45:11;;13416:2:16;3900:45:11::2;::::0;::::2;13398:21:16::0;13455:2;13435:18;;;13428:30;-1:-1:-1;;;13474:18:16;;;13467:43;13527:18;;3900:45:11::2;13214:337:16::0;3900:45:11::2;3956:23;3973:5;3956:16;:23::i;23838:705:9:-:0;23922:18;24013:19;24035:18;24047:5;24035:11;:18::i;:::-;24013:40;;24063:20;24086:28;24106:6;873:5:10;903:18;-1:-1:-1;;;;;903:18:10;;;;;;836:93;24086:28:9;24063:51;;24145:14;24129:30;;:13;:30;;;24125:412;;;1355:24:10;;24280:30:9;24296:14;24280:13;:30;:::i;:::-;24273:38;;:2;:38;:::i;:::-;24233:21;24248:5;24233:14;:21::i;:::-;-1:-1:-1;;;;;1977:33:10;;1951:7;1977:33;;;:26;:33;;;;;;24204:50:9;;;;:::i;:::-;:107;;;;:::i;:::-;:129;;;;:::i;:::-;24175:158;;24125:412;;;1355:24:10;;24472:30:9;24489:13;24472:14;:30;:::i;:::-;24465:38;;:2;:38;:::i;:::-;:60;;;;:::i;:::-;24423:21;24438:5;24423:14;:21::i;:::-;-1:-1:-1;;;;;1977:33:10;;1951:7;1977:33;;;:26;:33;;;;;;24394:26:9;1886:131:10;1517:121;1571:16;1606:6;:25;;1599:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1599:32:10;;;;;;;;;;;;;;;;;;;;;;;1517:121;:::o;6197:365:11:-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;6335:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;6363:22:::2;6379:5;6363:15;:22::i;:::-;6355:53;;;;-1:-1:-1::0;;;6355:53:11::2;;;;;;;:::i;:::-;6437:1;6426:8;:12;6418:50;;;::::0;-1:-1:-1;;;6418:50:11;;22838:2:16;6418:50:11::2;::::0;::::2;22820:21:16::0;22877:2;22857:18;;;22850:30;22916:27;22896:18;;;22889:55;22961:18;;6418:50:11::2;22636:349:16::0;6418:50:11::2;-1:-1:-1::0;;;;;2805:23:13;;:6;:23;;;:16;:23;;;;;;:34;;;6523:32:11;2805:34:13;;:23;6523:32:11::2;::::0;::::2;7697:1:::1;6197:365:::0;;;:::o;7315:281::-;7652:10;7641:7;471:12:10;;-1:-1:-1;;;;;471:12:10;;407:83;7641:7:11;-1:-1:-1;;;;;7641:21:11;;7633:54;;;;-1:-1:-1;;;7633:54:11;;;;;;;:::i;:::-;7465:8:::1;7785;7772:21;;:9;1071:6:10::0;1096:14;;;;1031:86;7772:9:11::1;:21;;;7764:45;;;;-1:-1:-1::0;;;7764:45:11::1;;;;;;;:::i;:::-;7493:22:::2;7509:5;7493:15;:22::i;:::-;7485:53;;;;-1:-1:-1::0;;;7485:53:11::2;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;2935:33:13;;:6;:33;;;:26;:33;;;;;:43;;;7549:40:11::2;7697:1:::1;7315:281:::0;;;:::o;1564:1043:13:-;-1:-1:-1;;;;;1648:28:13;;:6;:28;;;:21;:28;;;;;;;;1627:95;;;;-1:-1:-1;;;1627:95:13;;23192:2:16;1627:95:13;;;23174:21:16;23231:2;23211:18;;;23204:30;-1:-1:-1;;;23250:18:16;;;23243:50;23310:18;;1627:95:13;22990:344:16;1627:95:13;-1:-1:-1;;;;;1861:28:13;;1892:5;1861:28;;;:21;:28;;;;;;;;:36;;-1:-1:-1;;1861:36:13;;;1907:16;:23;;;;;:27;;;1944:26;:33;;;;;:37;;;2040:25;:32;;2225:160;2236:7;2232:1;:11;2225:160;;;2296:5;-1:-1:-1;;;;;2264:37:13;:6;:25;;2290:1;2264:28;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;2264:28:13;2260:81;2321:5;2260:81;2371:1;2366:6;2225:160;;;2404:7;2399:1;:12;2395:206;;2441:1;2431:7;:11;2427:119;;;2493:25;2519:11;2529:1;2519:7;:11;:::i;:::-;2493:38;;;;;;;;:::i;:::-;;;;;;;;;;;2462:25;:28;;-1:-1:-1;;;;;2493:38:13;;;;2488:1;;2462:28;;;;;;:::i;:::-;;;;;;;;;:69;;;;;-1:-1:-1;;;;;2462:69:13;;;;;-1:-1:-1;;;;;2462:69:13;;;;;;2427:119;2559:25;:31;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;2559:31:13;;;;;-1:-1:-1;;;;;;2559:31:13;;;;;;1617:990;;1564:1043;:::o;268:109::-;335:19;:35;;-1:-1:-1;;;;;;335:35:13;-1:-1:-1;;;;;335:35:13;;;;;;;;;;268:109::o;2336:287:0:-;1759:1;2468:7;;:19;2460:63;;;;-1:-1:-1;;;2460:63:0;;23805:2:16;2460:63:0;;;23787:21:16;23844:2;23824:18;;;23817:30;23883:33;23863:18;;;23856:61;23934:18;;2460:63:0;23603:355:16;2460:63:0;1759:1;2598:7;:18;2336:287::o;2976:247:10:-;3116:37;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3116:37:10;-1:-1:-1;;;3116:37:10;;;3086:77;;3035:5;;;;-1:-1:-1;;;;;3086:16:10;;;:77;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3052:111;;;3191:15;3180:36;;;;;;;;;;;;:::i;:::-;3173:43;2976:247;-1:-1:-1;;;2976:247:10:o;26569:475:9:-;26663:7;26733:21;26757:17;26768:5;26757:10;:17::i;:::-;26733:41;;26811:134;26858:5;26878:10;26910:4;26929:6;26811:26;:134::i;:::-;27024:13;27004:17;27015:5;27004:10;:17::i;:::-;:33;;;;:::i;:::-;26997:40;26569:475;-1:-1:-1;;;;26569:475:9:o;7420:3667::-;7577:22;7662:29;7678:6;:12;;;7662:15;:29::i;:::-;7654:60;;;;-1:-1:-1;;;7654:60:9;;;;;;;:::i;:::-;7745:22;;;;7724:119;;;;-1:-1:-1;;;7724:119:9;;24848:2:16;7724:119:9;;;24830:21:16;24887:2;24867:18;;;24860:30;24926:34;24906:18;;;24899:62;-1:-1:-1;;;24977:18:16;;;24970:34;25021:19;;7724:119:9;24646:400:16;7724:119:9;8078:24;8105:86;8134:6;:13;;;8161:6;:20;;;8105:15;:86::i;:::-;8078:113;;8228:1;8209:16;:20;8201:62;;;;-1:-1:-1;;;8201:62:9;;25253:2:16;8201:62:9;;;25235:21:16;25292:2;25272:18;;;25265:30;25331:31;25311:18;;;25304:59;25380:18;;8201:62:9;25051:353:16;8201:62:9;8334:37;8374:99;8403:6;:26;;;8443:6;:20;;;8374:15;:99::i;:::-;8334:139;;8504:6;:26;;;8534:1;8504:31;:68;;;;8571:1;8539:29;:33;8504:68;8483:142;;;;-1:-1:-1;;;8483:142:9;;25611:2:16;8483:142:9;;;25593:21:16;25650:2;25630:18;;;25623:30;25689:29;25669:18;;;25662:57;25736:18;;8483:142:9;25409:351:16;8483:142:9;8817:18;;;;1224:42:10;;8770:22:9;1224:42:10;;;:26;:42;;;;;;;8846:62:9;;;;-1:-1:-1;;;8846:62:9;;25967:2:16;8846:62:9;;;25949:21:16;26006:2;25986:18;;;25979:30;-1:-1:-1;;;26025:18:16;;;26018:51;26086:18;;8846:62:9;25765:345:16;8846:62:9;9059:28;9090:210;9119:137;9156:6;:18;;;9192:6;:12;;;9222:6;:20;;;9119:19;:137::i;:::-;9270:6;:20;;;9090:15;:210::i;:::-;9059:241;-1:-1:-1;9350:52:9;9373:29;9059:241;9350:52;:::i;:::-;9331:16;:71;9310:137;;;;-1:-1:-1;;;9310:137:9;;26317:2:16;9310:137:9;;;26299:21:16;26356:2;26336:18;;;26329:30;-1:-1:-1;;;26375:18:16;;;26368:49;26434:18;;9310:137:9;26115:343:16;9310:137:9;9915:27;9945:291;9982:244;;;;;;;;10029:1;9982:244;;;;;;10066:20;9982:244;;;;10125:29;9982:244;;;;10189:6;:22;;;9982:244;;;9945:23;:291::i;:::-;9915:321;;10285:19;10307:13;803:18:10;;-1:-1:-1;;;;;803:18:10;;707:123;10307:13:9;10285:35;;10397:121;10439:6;:12;;;10474:6;10495;:13;;;10397:21;:121::i;:::-;10856:6;-1:-1:-1;;;;;10856:32:9;;10896:11;10922:6;:12;;;10948:6;:13;;;10975:6;:18;;;11007:14;11035:7;11056:14;10856:224;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;14814:320:8:-;14893:7;14937:11;:6;14946:2;14937:11;:::i;:::-;14920:6;:13;:28;;14912:62;;;;-1:-1:-1;;;14912:62:8;;27689:2:16;14912:62:8;;;27671:21:16;27728:2;27708:18;;;27701:30;-1:-1:-1;;;27747:18:16;;;27740:51;27808:18;;14912:62:8;27487:345:16;14912:62:8;-1:-1:-1;15058:30:8;15074:4;15058:30;15052:37;;14814:320::o;12935:305::-;13013:6;13056:10;:6;13065:1;13056:10;:::i;:::-;13039:6;:13;:27;;13031:60;;;;-1:-1:-1;;;13031:60:8;;28039:2:16;13031:60:8;;;28021:21:16;28078:2;28058:18;;;28051:30;-1:-1:-1;;;28097:18:16;;;28090:50;28157:18;;13031:60:8;27837:344:16;13031:60:8;-1:-1:-1;13168:29:8;13184:3;13168:29;13162:36;;12935:305::o;27050:199:9:-;27117:7;-1:-1:-1;;;;;;27144:22:9;;;27136:54;;;;-1:-1:-1;;;27136:54:9;;28388:2:16;27136:54:9;;;28370:21:16;28427:2;28407:18;;;28400:30;-1:-1:-1;;;28446:18:16;;;28439:49;28505:18;;27136:54:9;28186:343:16;27136:54:9;-1:-1:-1;27231:8:9;27050:199::o;17279:2765::-;17375:12;17389:7;17398;17826:33;17862:10;678:15:10;;-1:-1:-1;;;;;678:15:10;;599:102;17862:10:9;-1:-1:-1;;;;;17862:18:9;;17894:22;17862:64;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;17862:64:9;;;;;;;;;;;;:::i;:::-;17826:100;;18331:25;18359:81;18409:13;:21;;;18359:36;:81::i;:::-;18331:109;;18458:34;18474:17;18458:15;:34::i;:::-;18450:67;;;;-1:-1:-1;;;18450:67:9;;23192:2:16;18450:67:9;;;23174:21:16;23231:2;23211:18;;;23204:30;-1:-1:-1;;;23250:18:16;;;23243:50;23310:18;;18450:67:9;22990:344:16;18450:67:9;18584:21;18608:29;18619:17;18608:10;:29::i;:::-;18584:53;;18691:19;18713:13;803:18:10;;-1:-1:-1;;;;;803:18:10;;707:123;18713:13:9;18691:35;;18959:28;18990:6;-1:-1:-1;;;;;18990:34:9;;19038:22;18990:80;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;18990:80:9;;;;;;;;;;;;:::i;:::-;18959:111;;19162:22;19219:13;19187:29;19198:17;19187:10;:29::i;:::-;:45;;;;:::i;:::-;19162:70;;19327:48;19390:6;-1:-1:-1;;;;;19390:31:9;;19422:15;19390:48;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;19390:48:9;;;;;;;;;;;;:::i;:::-;19327:111;;19581:51;19603:13;:28;;;1224:42:10;;1198:7;1224:42;;;:26;:42;;;;;;;1123:150;19581:51:9;19557:8;:20;;;:75;19536:145;;;;-1:-1:-1;;;19536:145:9;;33674:2:16;19536:145:9;;;33656:21:16;33713:2;33693:18;;;33686:30;33752:25;33732:18;;;33725:53;33795:18;;19536:145:9;33472:347:16;19536:145:9;19888:13;:22;;;-1:-1:-1;;;;;19774:146:9;19846:13;:28;;;19804:13;:28;;;19774:146;;;;;;;;;;;;19952:16;;;;19982:14;;-1:-1:-1;20010:17:9;;-1:-1:-1;17279:2765:9;;-1:-1:-1;;;;;;17279:2765:9:o;20050:752::-;20276:9;:14;20268:62;;;;-1:-1:-1;;;20268:62:9;;34026:2:16;20268:62:9;;;34008:21:16;34065:2;34045:18;;;34038:30;34104:34;34084:18;;;34077:62;-1:-1:-1;;;34155:18:16;;;34148:33;34198:19;;20268:62:9;33824:399:16;20268:62:9;20372:10;903:18:10;-1:-1:-1;;;;;903:18:10;;;;;;;20459:22:9;;;;:36;;;;;20485:10;20459:36;20455:341;;;20566:21;;-1:-1:-1;;;20566:21:9;;;;;1877:25:16;;;-1:-1:-1;;;;;20566:13:9;;;;;1850:18:16;;20566:21:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;20601:35:9;;-1:-1:-1;;;;;20601:27:9;;;-1:-1:-1;20601:35:9;;;;;-1:-1:-1;20629:6:9;;20601:35;;;;20629:6;20601:27;:35;;;;;;;;;;;;;;;;;;;;;20455:341;;;20667:118;20714:5;20738:9;20765:6;20667:22;:118::i;:::-;20197:605;20050:752;;;;:::o;20808:1394::-;21038:9;:14;21030:45;;;;-1:-1:-1;;;21030:45:9;;34430:2:16;21030:45:9;;;34412:21:16;34469:2;34449:18;;;34442:30;-1:-1:-1;;;34488:18:16;;;34481:48;34546:18;;21030:45:9;34228:342:16;21030:45:9;21289:10;21285:911;;;873:5:10;903:18;21343:23:9;;-1:-1:-1;;;21343:23:9;;;;;1877:25:16;;;903:18:10;;;;-1:-1:-1;;;;;903:18:10;;21343:15:9;;1850:18:16;;21343:23:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21430:9;-1:-1:-1;;;;;21422:27:9;:48;21459:10;21450:6;:19;;;;:::i;:::-;21422:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21539:14:9;;21535:93;;21573:40;;21581:10;;21573:40;;;;;21602:10;;21573:40;;;;21602:10;21581;21573:40;;;;;;;;;;;;;;;;;;;;;21535:93;21285:911;;;21693:10;903:18:10;;;;-1:-1:-1;;;;;903:18:10;21782:139:9;903:18:10;21861:9:9;21888:19;21897:10;21888:6;:19;:::i;21782:139::-;21990:14;;21986:200;;22024:147;22083:4;22111:10;22143;763:205:3;902:58;;-1:-1:-1;;;;;34767:32:16;;902:58:3;;;34749:51:16;34816:18;;;34809:34;;;875:86:3;;895:5;;-1:-1:-1;;;925:23:3;34722:18:16;;902:58:3;;;;-1:-1:-1;;902:58:3;;;;;;;;;;;;;;-1:-1:-1;;;;;902:58:3;-1:-1:-1;;;;;;902:58:3;;;;;;;;;;875:19;:86::i;12627:302:8:-;12704:5;12746:10;:6;12755:1;12746:10;:::i;:::-;12729:6;:13;:27;;12721:60;;;;-1:-1:-1;;;12721:60:8;;35056:2:16;12721:60:8;;;35038:21:16;35095:2;35075:18;;;35068:30;-1:-1:-1;;;35114:18:16;;;35107:49;35173:18;;12721:60:8;34854:343:16;12721:60:8;-1:-1:-1;12857:29:8;12873:3;12857:29;12851:36;;12627:302::o;14497:311::-;14576:7;14620:11;:6;14629:2;14620:11;:::i;:::-;14603:6;:13;:28;;14595:62;;;;-1:-1:-1;;;14595:62:8;;35404:2:16;14595:62:8;;;35386:21:16;35443:2;35423:18;;;35416:30;-1:-1:-1;;;35462:18:16;;;35455:51;35523:18;;14595:62:8;35202:345:16;1291:267:13;-1:-1:-1;;;;;1372:28:13;;:6;:28;;;:21;:28;;;;;;;;:37;1351:108;;;;-1:-1:-1;;;1351:108:13;;35754:2:16;1351:108:13;;;35736:21:16;35793:2;35773:18;;;35766:30;35832:26;35812:18;;;35805:54;35876:18;;1351:108:13;35552:348:16;1351:108:13;-1:-1:-1;;;;;1469:28:13;:6;:28;;;:21;:28;;;;;:35;;-1:-1:-1;;1469:35:13;1500:4;1469:35;;;;;;1514:25;:37;;;;;;;;;;;;;;-1:-1:-1;;;;;;1514:37:13;;;;;;1291:267::o;3229:370:10:-;3457:64;;;3515:4;3457:64;;;;5329:51:16;;;;3457:64:10;;;;;;;;;;5302:18:16;;;;3457:64:10;;;;;;;-1:-1:-1;;;;;3457:64:10;-1:-1:-1;;;3457:64:10;;;3423:112;;3287:15;;;;-1:-1:-1;;;;;3423:16:10;;;:112;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3377:158;;;3566:14;3555:37;;;;;;;;;;;;:::i;974:241:3:-;1139:68;;-1:-1:-1;;;;;36163:15:16;;;1139:68:3;;;36145:34:16;36215:15;;36195:18;;;36188:43;36247:18;;;36240:34;;;1112:96:3;;1132:5;;-1:-1:-1;;;1162:27:3;36080:18:16;;1139:68:3;35905:375:16;1475:603:3;1830:10;;;1829:62;;-1:-1:-1;1846:39:3;;-1:-1:-1;;;1846:39:3;;1870:4;1846:39;;;36497:34:16;-1:-1:-1;;;;;36567:15:16;;;36547:18;;;36540:43;1846:15:3;;;;;36432:18:16;;1846:39:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;1829:62;1808:163;;;;-1:-1:-1;;;1808:163:3;;36796:2:16;1808:163:3;;;36778:21:16;36835:2;36815:18;;;36808:30;36874:34;36854:18;;;36847:62;-1:-1:-1;;;36925:18:16;;;36918:52;36987:19;;1808:163:3;36594:418:16;1808:163:3;2008:62;;-1:-1:-1;;;;;34767:32:16;;2008:62:3;;;34749:51:16;34816:18;;;34809:34;;;1981:90:3;;2001:5;;-1:-1:-1;;;2031:22:3;34722:18:16;;2008:62:3;34575:274:16;3747:706:3;4166:23;4192:69;4220:4;4192:69;;;;;;;;;;;;;;;;;4200:5;-1:-1:-1;;;;;4192:27:3;;;:69;;;;;:::i;:::-;4275:17;;4166:95;;-1:-1:-1;4275:21:3;4271:176;;4370:10;4359:30;;;;;;;;;;;;:::i;:::-;4351:85;;;;-1:-1:-1;;;4351:85:3;;37469:2:16;4351:85:3;;;37451:21:16;37508:2;37488:18;;;37481:30;37547:34;37527:18;;;37520:62;-1:-1:-1;;;37598:18:16;;;37591:40;37648:19;;4351:85:3;37267:406:16;3873:223:4;4006:12;4037:52;4059:6;4067:4;4073:1;4076:12;4006;5241;5255:23;5282:6;-1:-1:-1;;;;;5282:11:4;5301:5;5308:4;5282:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5240:73;;;;5330:69;5357:6;5365:7;5374:10;5386:12;5330:26;:69::i;:::-;5323:76;4960:446;-1:-1:-1;;;;;;;4960:446:4:o;7466:628::-;7646:12;7674:7;7670:418;;;7701:10;:17;7722:1;7701:22;7697:286;;-1:-1:-1;;;;;1465:19:4;;;7908:60;;;;-1:-1:-1;;;7908:60:4;;38287:2:16;7908:60:4;;;38269:21:16;38326:2;38306:18;;;38299:30;38365:31;38345:18;;;38338:59;38414:18;;7908:60:4;38085:353:16;7908:60:4;-1:-1:-1;8003:10:4;7996:17;;7670:418;8044:33;8052:10;8064:12;8775:17;;:21;8771:379;;9003:10;8997:17;9059:15;9046:10;9042:2;9038:19;9031:44;8771:379;9126:12;9119:20;;-1:-1:-1;;;9119:20:4;;;;;;;;:::i;14:117:16:-;99:6;92:5;88:18;81:5;78:29;68:57;;121:1;118;111:12;68:57;14:117;:::o;136:131::-;-1:-1:-1;;;;;211:31:16;;201:42;;191:70;;257:1;254;247:12;272:386;339:6;347;400:2;388:9;379:7;375:23;371:32;368:52;;;416:1;413;406:12;368:52;455:9;442:23;474:30;498:5;474:30;:::i;:::-;523:5;-1:-1:-1;580:2:16;565:18;;552:32;593:33;552:32;593:33;:::i;:::-;645:7;635:17;;;272:386;;;;;:::o;663:121::-;748:10;741:5;737:22;730:5;727:33;717:61;;774:1;771;764:12;789:732;891:6;899;907;915;923;931;984:3;972:9;963:7;959:23;955:33;952:53;;;1001:1;998;991:12;952:53;1040:9;1027:23;1059:31;1084:5;1059:31;:::i;:::-;1109:5;-1:-1:-1;1161:2:16;1146:18;;1133:32;;-1:-1:-1;1212:2:16;1197:18;;1184:32;;-1:-1:-1;1268:2:16;1253:18;;1240:32;1281;1240;1281;:::i;:::-;1332:7;-1:-1:-1;1386:3:16;1371:19;;1358:33;;-1:-1:-1;1443:3:16;1428:19;;1415:33;1457:32;1415:33;1457:32;:::i;:::-;1508:7;1498:17;;;789:732;;;;;;;;:::o;1913:114::-;1997:4;1990:5;1986:16;1979:5;1976:27;1966:55;;2017:1;2014;2007:12;2032:311;2098:6;2106;2159:2;2147:9;2138:7;2134:23;2130:32;2127:52;;;2175:1;2172;2165:12;2127:52;2211:9;2198:23;2188:33;;2271:2;2260:9;2256:18;2243:32;2284:29;2307:5;2284:29;:::i;2348:521::-;2432:6;2440;2448;2456;2509:3;2497:9;2488:7;2484:23;2480:33;2477:53;;;2526:1;2523;2516:12;2477:53;2562:9;2549:23;2539:33;;2622:2;2611:9;2607:18;2594:32;2635:30;2659:5;2635:30;:::i;:::-;2684:5;-1:-1:-1;2736:2:16;2721:18;;2708:32;;-1:-1:-1;2792:2:16;2777:18;;2764:32;2805;2764;2805;:::i;:::-;2348:521;;;;-1:-1:-1;2348:521:16;;-1:-1:-1;;2348:521:16:o;2874:247::-;2933:6;2986:2;2974:9;2965:7;2961:23;2957:32;2954:52;;;3002:1;2999;2992:12;2954:52;3041:9;3028:23;3060:31;3085:5;3060:31;:::i;3126:127::-;3187:10;3182:3;3178:20;3175:1;3168:31;3218:4;3215:1;3208:15;3242:4;3239:1;3232:15;3258:253;3330:2;3324:9;3372:4;3360:17;;-1:-1:-1;;;;;3392:34:16;;3428:22;;;3389:62;3386:88;;;3454:18;;:::i;:::-;3490:2;3483:22;3258:253;:::o;3516:255::-;3588:2;3582:9;3630:6;3618:19;;-1:-1:-1;;;;;3652:34:16;;3688:22;;;3649:62;3646:88;;;3714:18;;:::i;3776:255::-;3848:2;3842:9;3890:6;3878:19;;-1:-1:-1;;;;;3912:34:16;;3948:22;;;3909:62;3906:88;;;3974:18;;:::i;4036:275::-;4107:2;4101:9;4172:2;4153:13;;-1:-1:-1;;4149:27:16;4137:40;;-1:-1:-1;;;;;4192:34:16;;4228:22;;;4189:62;4186:88;;;4254:18;;:::i;:::-;4290:2;4283:22;4036:275;;-1:-1:-1;4036:275:16:o;4316:186::-;4364:4;-1:-1:-1;;;;;4389:6:16;4386:30;4383:56;;;4419:18;;:::i;:::-;-1:-1:-1;4485:2:16;4464:15;-1:-1:-1;;4460:29:16;4491:4;4456:40;;4316:186::o;4507:671::-;4575:6;4628:2;4616:9;4607:7;4603:23;4599:32;4596:52;;;4644:1;4641;4634:12;4596:52;4684:9;4671:23;-1:-1:-1;;;;;4709:6:16;4706:30;4703:50;;;4749:1;4746;4739:12;4703:50;4772:22;;4825:4;4817:13;;4813:27;-1:-1:-1;4803:55:16;;4854:1;4851;4844:12;4803:55;4890:2;4877:16;4915:48;4931:31;4959:2;4931:31;:::i;:::-;4915:48;:::i;:::-;4986:2;4979:5;4972:17;5026:7;5021:2;5016;5012;5008:11;5004:20;5001:33;4998:53;;;5047:1;5044;5037:12;4998:53;5102:2;5097;5093;5089:11;5084:2;5077:5;5073:14;5060:45;5146:1;5125:14;;;5141:2;5121:23;5114:34;;;;5129:5;4507:671;-1:-1:-1;;;;4507:671:16:o;5391:313::-;5458:6;5466;5519:2;5507:9;5498:7;5494:23;5490:32;5487:52;;;5535:1;5532;5525:12;5487:52;5574:9;5561:23;5593:30;5617:5;5593:30;:::i;:::-;5642:5;5694:2;5679:18;;;;5666:32;;-1:-1:-1;;;5391:313:16:o;5709:591::-;5779:6;5787;5840:2;5828:9;5819:7;5815:23;5811:32;5808:52;;;5856:1;5853;5846:12;5808:52;5896:9;5883:23;-1:-1:-1;;;;;5966:2:16;5958:6;5955:14;5952:34;;;5982:1;5979;5972:12;5952:34;6020:6;6009:9;6005:22;5995:32;;6065:7;6058:4;6054:2;6050:13;6046:27;6036:55;;6087:1;6084;6077:12;6036:55;6127:2;6114:16;6153:2;6145:6;6142:14;6139:34;;;6169:1;6166;6159:12;6139:34;6214:7;6209:2;6200:6;6196:2;6192:15;6188:24;6185:37;6182:57;;;6235:1;6232;6225:12;6182:57;6266:2;6258:11;;;;;6288:6;;-1:-1:-1;5709:591:16;;-1:-1:-1;;;;5709:591:16:o;6305:523::-;6379:6;6387;6395;6448:2;6436:9;6427:7;6423:23;6419:32;6416:52;;;6464:1;6461;6454:12;6416:52;6503:9;6490:23;6522:30;6546:5;6522:30;:::i;:::-;6571:5;-1:-1:-1;6628:2:16;6613:18;;6600:32;6641:33;6600:32;6641:33;:::i;:::-;6693:7;-1:-1:-1;6752:2:16;6737:18;;6724:32;6765:31;6724:32;6765:31;:::i;:::-;6815:7;6805:17;;;6305:523;;;;;:::o;7025:245::-;7083:6;7136:2;7124:9;7115:7;7111:23;7107:32;7104:52;;;7152:1;7149;7142:12;7104:52;7191:9;7178:23;7210:30;7234:5;7210:30;:::i;8235:118::-;8321:5;8314:13;8307:21;8300:5;8297:32;8287:60;;8343:1;8340;8333:12;8358:380;8422:6;8430;8483:2;8471:9;8462:7;8458:23;8454:32;8451:52;;;8499:1;8496;8489:12;8451:52;8538:9;8525:23;8557:30;8581:5;8557:30;:::i;:::-;8606:5;-1:-1:-1;8663:2:16;8648:18;;8635:32;8676:30;8635:32;8676:30;:::i;8969:315::-;9037:6;9045;9098:2;9086:9;9077:7;9073:23;9069:32;9066:52;;;9114:1;9111;9104:12;9066:52;9153:9;9140:23;9172:31;9197:5;9172:31;:::i;9482:713::-;9576:6;9629:3;9617:9;9608:7;9604:23;9600:33;9597:53;;;9646:1;9643;9636:12;9597:53;9679:2;9673:9;9721:3;9713:6;9709:16;9791:6;9779:10;9776:22;-1:-1:-1;;;;;9743:10:16;9740:34;9737:62;9734:88;;;9802:18;;:::i;:::-;9838:2;9831:22;9875:23;;9907:29;9875:23;9907:29;:::i;:::-;9960:5;9952:6;9945:21;;10027:2;10016:9;10012:18;9999:32;9994:2;9986:6;9982:15;9975:57;10093:2;10082:9;10078:18;10065:32;10060:2;10052:6;10048:15;10041:57;10159:2;10148:9;10144:18;10131:32;10126:2;10118:6;10114:15;10107:57;10183:6;10173:16;;;9482:713;;;;:::o;10200:250::-;10285:1;10295:113;10309:6;10306:1;10303:13;10295:113;;;10385:11;;;10379:18;10366:11;;;10359:39;10331:2;10324:10;10295:113;;;-1:-1:-1;;10442:1:16;10424:16;;10417:27;10200:250::o;10455:270::-;10496:3;10534:5;10528:12;10561:6;10556:3;10549:19;10577:76;10646:6;10639:4;10634:3;10630:14;10623:4;10616:5;10612:16;10577:76;:::i;:::-;10707:2;10686:15;-1:-1:-1;;10682:29:16;10673:39;;;;10714:4;10669:50;;10455:270;-1:-1:-1;;10455:270:16:o;10730:217::-;10877:2;10866:9;10859:21;10840:4;10897:44;10937:2;10926:9;10922:18;10914:6;10897:44;:::i;11403:658::-;11574:2;11626:21;;;11696:13;;11599:18;;;11718:22;;;11545:4;;11574:2;11797:15;;;;11771:2;11756:18;;;11545:4;11840:195;11854:6;11851:1;11848:13;11840:195;;;11919:13;;-1:-1:-1;;;;;11915:39:16;11903:52;;12010:15;;;;11975:12;;;;11951:1;11869:9;11840:195;;;-1:-1:-1;12052:3:16;;11403:658;-1:-1:-1;;;;;;11403:658:16:o;12066:454::-;12142:6;12150;12158;12211:2;12199:9;12190:7;12186:23;12182:32;12179:52;;;12227:1;12224;12217:12;12179:52;12266:9;12253:23;12285:30;12309:5;12285:30;:::i;:::-;12334:5;-1:-1:-1;12391:2:16;12376:18;;12363:32;12404:33;12363:32;12404:33;:::i;:::-;12066:454;;12456:7;;-1:-1:-1;;;12510:2:16;12495:18;;;;12482:32;;12066:454::o;12525:344::-;12727:2;12709:21;;;12766:2;12746:18;;;12739:30;-1:-1:-1;;;12800:2:16;12785:18;;12778:50;12860:2;12845:18;;12525:344::o;12874:335::-;13076:2;13058:21;;;13115:2;13095:18;;;13088:30;-1:-1:-1;;;13149:2:16;13134:18;;13127:41;13200:2;13185:18;;12874:335::o;13912:184::-;13982:6;14035:2;14023:9;14014:7;14010:23;14006:32;14003:52;;;14051:1;14048;14041:12;14003:52;-1:-1:-1;14074:16:16;;13912:184;-1:-1:-1;13912:184:16:o;14448:127::-;14509:10;14504:3;14500:20;14497:1;14490:31;14540:4;14537:1;14530:15;14564:4;14561:1;14554:15;14580:151;14670:4;14663:12;;;14649;;;14645:31;;14688:14;;14685:40;;;14705:18;;:::i;14736:422::-;14825:1;14868:5;14825:1;14882:270;14903:7;14893:8;14890:21;14882:270;;;14962:4;14958:1;14954:6;14950:17;14944:4;14941:27;14938:53;;;14971:18;;:::i;:::-;15021:7;15011:8;15007:22;15004:55;;;15041:16;;;;15004:55;15120:22;;;;15080:15;;;;14882:270;;;14886:3;14736:422;;;;;:::o;15163:806::-;15212:5;15242:8;15232:80;;-1:-1:-1;15283:1:16;15297:5;;15232:80;15331:4;15321:76;;-1:-1:-1;15368:1:16;15382:5;;15321:76;15413:4;15431:1;15426:59;;;;15499:1;15494:130;;;;15406:218;;15426:59;15456:1;15447:10;;15470:5;;;15494:130;15531:3;15521:8;15518:17;15515:43;;;15538:18;;:::i;:::-;-1:-1:-1;;15594:1:16;15580:16;;15609:5;;15406:218;;15708:2;15698:8;15695:16;15689:3;15683:4;15680:13;15676:36;15670:2;15660:8;15657:16;15652:2;15646:4;15643:12;15639:35;15636:77;15633:159;;;-1:-1:-1;15745:19:16;;;15777:5;;15633:159;15824:34;15849:8;15843:4;15824:34;:::i;:::-;15894:6;15890:1;15886:6;15882:19;15873:7;15870:32;15867:58;;;15905:18;;:::i;:::-;15943:20;;15163:806;-1:-1:-1;;;15163:806:16:o;15974:140::-;16032:5;16061:47;16102:4;16092:8;16088:19;16082:4;16061:47;:::i;16119:217::-;16159:1;16185;16175:132;;16229:10;16224:3;16220:20;16217:1;16210:31;16264:4;16261:1;16254:15;16292:4;16289:1;16282:15;16175:132;-1:-1:-1;16321:9:16;;16119:217::o;16341:168::-;16414:9;;;16445;;16462:15;;;16456:22;;16442:37;16432:71;;16483:18;;:::i;16875:128::-;16942:9;;;16963:11;;;16960:37;;;16977:18;;:::i;17272:251::-;17342:6;17395:2;17383:9;17374:7;17370:23;17366:32;17363:52;;;17411:1;17408;17401:12;17363:52;17443:9;17437:16;17462:31;17487:5;17462:31;:::i;18839:125::-;18904:9;;;18925:10;;;18922:36;;;18938:18;;:::i;22289:342::-;22491:2;22473:21;;;22530:2;22510:18;;;22503:30;-1:-1:-1;;;22564:2:16;22549:18;;22542:48;22622:2;22607:18;;22289:342::o;23339:127::-;23400:10;23395:3;23391:20;23388:1;23381:31;23431:4;23428:1;23421:15;23455:4;23452:1;23445:15;23471:127;23532:10;23527:3;23523:20;23520:1;23513:31;23563:4;23560:1;23553:15;23587:4;23584:1;23577:15;23963:287;24092:3;24130:6;24124:13;24146:66;24205:6;24200:3;24193:4;24185:6;24181:17;24146:66;:::i;:::-;24228:16;;;;;23963:287;-1:-1:-1;;23963:287:16:o;24255:134::-;24332:13;;24354:29;24332:13;24354:29;:::i;:::-;24255:134;;;:::o;24394:247::-;24462:6;24515:2;24503:9;24494:7;24490:23;24486:32;24483:52;;;24531:1;24528;24521:12;24483:52;24563:9;24557:16;24582:29;24605:5;24582:29;:::i;26463:628::-;26775:1;26771;26766:3;26762:11;26758:19;26750:6;26746:32;26735:9;26728:51;26815:6;26810:2;26799:9;26795:18;26788:34;26870:6;26862;26858:19;26853:2;26842:9;26838:18;26831:47;26914:6;26909:2;26898:9;26894:18;26887:34;26970:10;26962:6;26958:23;26952:3;26941:9;26937:19;26930:52;27019:3;27013;27002:9;26998:19;26991:32;26709:4;27040:45;27080:3;27069:9;27065:19;27057:6;27040:45;:::i;:::-;27032:53;26463:628;-1:-1:-1;;;;;;;;26463:628:16:o;27096:175::-;27174:13;;-1:-1:-1;;;;;27216:30:16;;27206:41;;27196:69;;27261:1;27258;27251:12;27276:206;27345:6;27398:2;27386:9;27377:7;27373:23;27369:32;27366:52;;;27414:1;27411;27404:12;27366:52;27437:39;27466:9;27437:39;:::i;28534:136::-;28612:13;;28634:30;28612:13;28634:30;:::i;28675:136::-;28753:13;;28775:30;28753:13;28775:30;:::i;28816:441::-;28869:5;28922:3;28915:4;28907:6;28903:17;28899:27;28889:55;;28940:1;28937;28930:12;28889:55;28969:6;28963:13;29000:48;29016:31;29044:2;29016:31;:::i;29000:48::-;29073:2;29064:7;29057:19;29119:3;29112:4;29107:2;29099:6;29095:15;29091:26;29088:35;29085:55;;;29136:1;29133;29126:12;29085:55;29149:77;29223:2;29216:4;29207:7;29203:18;29196:4;29188:6;29184:17;29149:77;:::i;29262:1291::-;29336:5;29389:3;29382:4;29374:6;29370:17;29366:27;29356:55;;29407:1;29404;29397:12;29356:55;29436:6;29430:13;29462:4;-1:-1:-1;;;;;29481:2:16;29478:26;29475:52;;;29507:18;;:::i;:::-;29547:36;29579:2;29574;29571:1;29567:10;29563:19;29547:36;:::i;:::-;29617:15;;;29703:1;29699:10;;;;29687:23;;29683:32;;;29648:12;;;;29727:15;;;29724:35;;;29755:1;29752;29745:12;29724:35;29791:2;29783:6;29779:15;29803:721;29819:6;29814:3;29811:15;29803:721;;;29897:4;29891:3;29886;29882:13;29878:24;29875:114;;;29943:1;29972:2;29968;29961:14;29875:114;30015:22;;:::i;:::-;30070:3;30064:10;30057:5;30050:25;30126:2;30121:3;30117:12;30111:19;30106:2;30099:5;30095:14;30088:43;30154:2;30199;30194:3;30190:12;30184:19;30216:31;30239:7;30216:31;:::i;:::-;30267:14;;;30260:31;30314:2;30350:12;;;30344:19;30376:31;30344:19;30376:31;:::i;:::-;30427:14;;;30420:31;30464:18;;30502:12;;;;29845:4;29836:14;29803:721;;;-1:-1:-1;30542:5:16;29262:1291;-1:-1:-1;;;;;;29262:1291:16:o;30558:1502::-;30648:6;30701:2;30689:9;30680:7;30676:23;30672:32;30669:52;;;30717:1;30714;30707:12;30669:52;30750:9;30744:16;-1:-1:-1;;;;;30820:2:16;30812:6;30809:14;30806:34;;;30836:1;30833;30826:12;30806:34;30859:22;;;;30915:6;30897:16;;;30893:29;30890:49;;;30935:1;30932;30925:12;30890:49;30961:22;;:::i;:::-;31006:31;31034:2;31006:31;:::i;:::-;30999:5;30992:46;31070:41;31107:2;31103;31099:11;31070:41;:::i;:::-;31065:2;31058:5;31054:14;31047:65;31144:41;31181:2;31177;31173:11;31144:41;:::i;:::-;31139:2;31132:5;31128:14;31121:65;31218:41;31255:2;31251;31247:11;31218:41;:::i;:::-;31213:2;31206:5;31202:14;31195:65;31307:3;31303:2;31299:12;31293:19;31287:3;31280:5;31276:15;31269:44;31346:42;31383:3;31379:2;31375:12;31346:42;:::i;:::-;31340:3;31333:5;31329:15;31322:67;31422:41;31458:3;31454:2;31450:12;31422:41;:::i;:::-;31416:3;31409:5;31405:15;31398:66;31503:3;31499:2;31495:12;31489:19;31533:2;31523:8;31520:16;31517:36;;;31549:1;31546;31539:12;31517:36;31586:55;31633:7;31622:8;31618:2;31614:17;31586:55;:::i;:::-;31580:3;31573:5;31569:15;31562:80;;31661:3;31696:41;31733:2;31729;31725:11;31696:41;:::i;:::-;31680:14;;;31673:65;31757:3;31791:11;;;31785:18;31815:16;;;31812:36;;;31844:1;31841;31834:12;31812:36;31880:76;31948:7;31937:8;31933:2;31929:17;31880:76;:::i;:::-;31864:14;;;31857:100;;;;-1:-1:-1;31976:3:16;32017:11;;;32011:18;31995:14;;;31988:42;;;;-1:-1:-1;31868:5:16;30558:1502;-1:-1:-1;;;30558:1502:16:o;32065:335::-;32144:6;32197:2;32185:9;32176:7;32172:23;32168:32;32165:52;;;32213:1;32210;32203:12;32165:52;32246:9;32240:16;-1:-1:-1;;;;;32271:6:16;32268:30;32265:50;;;32311:1;32308;32301:12;32265:50;32334:60;32386:7;32377:6;32366:9;32362:22;32334:60;:::i;32405:1062::-;32511:6;32564:2;32552:9;32543:7;32539:23;32535:32;32532:52;;;32580:1;32577;32570:12;32532:52;32613:9;32607:16;-1:-1:-1;;;;;32683:2:16;32675:6;32672:14;32669:34;;;32699:1;32696;32689:12;32669:34;32722:22;;;;32778:6;32760:16;;;32756:29;32753:49;;;32798:1;32795;32788:12;32753:49;32824:22;;:::i;:::-;32869:31;32897:2;32869:31;:::i;:::-;32862:5;32855:46;32947:2;32943;32939:11;32933:18;32928:2;32921:5;32917:14;32910:42;32998:2;32994;32990:11;32984:18;32979:2;32972:5;32968:14;32961:42;33035:41;33072:2;33068;33064:11;33035:41;:::i;:::-;33030:2;33023:5;33019:14;33012:65;33124:3;33120:2;33116:12;33110:19;33104:3;33097:5;33093:15;33086:44;33163:42;33200:3;33196:2;33192:12;33163:42;:::i;:::-;33157:3;33150:5;33146:15;33139:67;33253:3;33249:2;33245:12;33239:19;33233:3;33226:5;33222:15;33215:44;33298:3;33294:2;33290:12;33284:19;33328:2;33318:8;33315:16;33312:36;;;33344:1;33341;33334:12;33312:36;33381:55;33428:7;33417:8;33413:2;33409:17;33381:55;:::i;:::-;33375:3;33364:15;;33357:80;-1:-1:-1;33368:5:16;32405:1062;-1:-1:-1;;;;;32405:1062:16:o;37017:245::-;37084:6;37137:2;37125:9;37116:7;37112:23;37108:32;37105:52;;;37153:1;37150;37143:12;37105:52;37185:9;37179:16;37204:28;37226:5;37204:28;:::i

Swarm Source

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