Sepolia Testnet

Contract

0x70b1CD25Aa1DEbEf2BCa0eDbc11228C5EB4dAD0F
Source Code Source Code

Overview

ETH Balance

0 ETH

More Info

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Amount
Transfer ETH98521492025-12-16 9:34:3628 days ago1765877676IN
0x70b1CD25...5EB4dAD0F
0.52002449 ETH0.000186250.52540551
Transfer ETH98458902025-12-15 12:38:4829 days ago1765802328IN
0x70b1CD25...5EB4dAD0F
0.52002596 ETH0.00000120.00338515
Transfer ETH98442852025-12-15 7:16:4829 days ago1765783008IN
0x70b1CD25...5EB4dAD0F
0.50002656 ETH0.000000650.00186
Transfer ETH98394872025-12-14 15:10:2430 days ago1765725024IN
0x70b1CD25...5EB4dAD0F
0.52002981 ETH0.000001060.00300001
Transfer ETH98383092025-12-14 11:14:2430 days ago1765710864IN
0x70b1CD25...5EB4dAD0F
0.51002954 ETH0.000000420.00120001
Transfer ETH98332682025-12-13 18:25:0031 days ago1765650300IN
0x70b1CD25...5EB4dAD0F
2.50002787 ETH0.00000040.00114485
Transfer ETH98315132025-12-13 12:33:4831 days ago1765629228IN
0x70b1CD25...5EB4dAD0F
2.50002764 ETH0.000000420.00120001
Transfer ETH98293202025-12-13 5:13:4831 days ago1765602828IN
0x70b1CD25...5EB4dAD0F
0.0100277 ETH0.000000420.0012
Transfer ETH98259822025-12-12 18:02:1232 days ago1765562532IN
0x70b1CD25...5EB4dAD0F
2.50002914 ETH0.000000380.00110001
Transfer ETH98235442025-12-12 9:52:4832 days ago1765533168IN
0x70b1CD25...5EB4dAD0F
2.50002885 ETH0.001516394.27740259
Transfer ETH98178862025-12-11 14:57:3633 days ago1765465056IN
0x70b1CD25...5EB4dAD0F
2.50002549 ETH0.000000420.00120001
Transfer ETH98172712025-12-11 12:54:1233 days ago1765457652IN
0x70b1CD25...5EB4dAD0F
2.50002555 ETH0.000000380.00110001
Transfer ETH98115462025-12-10 17:46:4834 days ago1765388808IN
0x70b1CD25...5EB4dAD0F
2.5000269 ETH0.000003540.01000002
Transfer ETH98099952025-12-10 12:35:4834 days ago1765370148IN
0x70b1CD25...5EB4dAD0F
2.50002711 ETH0.000000380.0011
Transfer ETH98082722025-12-10 6:48:0034 days ago1765349280IN
0x70b1CD25...5EB4dAD0F
5.00002748 ETH0.000000420.0012
Transfer ETH97975872025-12-08 18:20:2436 days ago1765218024IN
0x70b1CD25...5EB4dAD0F
2.60002474 ETH0.000000420.0012
Transfer ETH97961952025-12-08 13:38:4836 days ago1765201128IN
0x70b1CD25...5EB4dAD0F
2.40002488 ETH0.00001380.03892771
Transfer ETH97898522025-12-07 16:27:1237 days ago1765124832IN
0x70b1CD25...5EB4dAD0F
2.60002494 ETH0.000000350.00100525
Transfer ETH97881122025-12-07 10:38:3637 days ago1765103916IN
0x70b1CD25...5EB4dAD0F
2.400025 ETH0.000002110.0059636
Transfer ETH97823422025-12-06 15:22:2438 days ago1765034544IN
0x70b1CD25...5EB4dAD0F
2.63002556 ETH0.00000360.01017753
Transfer ETH97817762025-12-06 13:29:0038 days ago1765027740IN
0x70b1CD25...5EB4dAD0F
25.00002539 ETH0.000000410.00115972
Transfer ETH97811662025-12-06 11:26:3638 days ago1765020396IN
0x70b1CD25...5EB4dAD0F
28.00002518 ETH0.000531781.5
Transfer ETH97807342025-12-06 10:00:0038 days ago1765015200IN
0x70b1CD25...5EB4dAD0F
4.16002524 ETH0.00000070.002
Transfer ETH97801592025-12-06 8:04:1238 days ago1765008252IN
0x70b1CD25...5EB4dAD0F
3.00002535 ETH0.000000350.001
Transfer ETH97752912025-12-05 15:19:0039 days ago1764947940IN
0x70b1CD25...5EB4dAD0F
2.64002479 ETH0.000000530.00150105
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
Amount
Request Executio...98521492025-12-16 9:34:3628 days ago1765877676
0x70b1CD25...5EB4dAD0F
0.00000411 ETH
Transfer98521492025-12-16 9:34:3628 days ago1765877676
0x70b1CD25...5EB4dAD0F
0.00002037 ETH
Deposit98521492025-12-16 9:34:3628 days ago1765877676
0x70b1CD25...5EB4dAD0F
0.52 ETH
Request Executio...98458902025-12-15 12:38:4829 days ago1765802328
0x70b1CD25...5EB4dAD0F
0.00000386 ETH
Transfer98458902025-12-15 12:38:4829 days ago1765802328
0x70b1CD25...5EB4dAD0F
0.00002209 ETH
Deposit98458902025-12-15 12:38:4829 days ago1765802328
0x70b1CD25...5EB4dAD0F
0.52 ETH
Request Executio...98442852025-12-15 7:16:4829 days ago1765783008
0x70b1CD25...5EB4dAD0F
0.00000389 ETH
Transfer98442852025-12-15 7:16:4829 days ago1765783008
0x70b1CD25...5EB4dAD0F
0.00002267 ETH
Deposit98442852025-12-15 7:16:4829 days ago1765783008
0x70b1CD25...5EB4dAD0F
0.5 ETH
Request Executio...98394872025-12-14 15:10:2430 days ago1765725024
0x70b1CD25...5EB4dAD0F
0.00000397 ETH
Transfer98394872025-12-14 15:10:2430 days ago1765725024
0x70b1CD25...5EB4dAD0F
0.00002584 ETH
Deposit98394872025-12-14 15:10:2430 days ago1765725024
0x70b1CD25...5EB4dAD0F
0.52 ETH
Request Executio...98383092025-12-14 11:14:2430 days ago1765710864
0x70b1CD25...5EB4dAD0F
0.00000392 ETH
Transfer98383092025-12-14 11:14:2430 days ago1765710864
0x70b1CD25...5EB4dAD0F
0.00002561 ETH
Deposit98383092025-12-14 11:14:2430 days ago1765710864
0x70b1CD25...5EB4dAD0F
0.51 ETH
Request Executio...98332682025-12-13 18:25:0031 days ago1765650300
0x70b1CD25...5EB4dAD0F
0.00000398 ETH
Transfer98332682025-12-13 18:25:0031 days ago1765650300
0x70b1CD25...5EB4dAD0F
0.00002388 ETH
Deposit98332682025-12-13 18:25:0031 days ago1765650300
0x70b1CD25...5EB4dAD0F
2.5 ETH
Request Executio...98315132025-12-13 12:33:4831 days ago1765629228
0x70b1CD25...5EB4dAD0F
0.00000397 ETH
Transfer98315132025-12-13 12:33:4831 days ago1765629228
0x70b1CD25...5EB4dAD0F
0.00002366 ETH
Deposit98315132025-12-13 12:33:4831 days ago1765629228
0x70b1CD25...5EB4dAD0F
2.5 ETH
Request Executio...98293202025-12-13 5:13:4831 days ago1765602828
0x70b1CD25...5EB4dAD0F
0.000004 ETH
Transfer98293202025-12-13 5:13:4831 days ago1765602828
0x70b1CD25...5EB4dAD0F
0.0000237 ETH
Deposit98293202025-12-13 5:13:4831 days ago1765602828
0x70b1CD25...5EB4dAD0F
0.01 ETH
Request Executio...98259822025-12-12 18:02:1232 days ago1765562532
0x70b1CD25...5EB4dAD0F
0.00000404 ETH
View All Internal Transactions
Loading...
Loading

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MultiTokenNttWithExecutor

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;

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

import "example-messaging-executor/evm/src/interfaces/IExecutor.sol";
import "example-messaging-executor/evm/src/libraries/ExecutorMessages.sol";

import "native-token-transfers/evm/src/libraries/TrimmedAmount.sol";

import "./interfaces/IMultiTokenNtt.sol";
import "./interfaces/IMultiTokenNttWithExecutor.sol";

string constant MultiTokenNttWithExecutorVersion = "MultiTokenNttWithExecutor-0.0.1";

/// @title MultiTokenNttWithExecutor
/// @author Wormhole Project Contributors.
/// @notice The MultiTokenNttWithExecutor contract is a shim contract that initiates
///         a Monad Bridge transfer using the executor for relaying.
contract MultiTokenNttWithExecutor is IMultiTokenNttWithExecutor {
    using TrimmedAmountLib for uint256;
    using TrimmedAmountLib for TrimmedAmount;

    uint16 public immutable chainId;
    IExecutor public immutable executor;

    string public constant VERSION = MultiTokenNttWithExecutorVersion;

    constructor(uint16 _chainId, address _executor) {
        assert(_chainId != 0);
        assert(_executor != address(0));
        chainId = _chainId;
        executor = IExecutor(_executor);
    }

    // ==================== External Interface ===============================================

    function transfer(
        address multiTokenNtt,
        address token,
        uint256 amount,
        uint16 recipientChain,
        bytes32 recipient,
        bytes32 refundAddress,
        bytes memory transceiverInstructions,
        ExecutorArgs calldata executorArgs,
        FeeArgs calldata feeArgs
    ) external payable returns (uint64 sequence) {
        // TODO: Is it confusing having two refund addresses (the function arg and the executor arg)?
        // Can we use the arg everywhere (converting it to address for the executor)?

        IMultiTokenNtt mtNtt = IMultiTokenNtt(multiTokenNtt);
        uint8 decimals = _getDecimals(token);

        // Custody the tokens in this contract and approve the Monad bridge to spend them.
        // Not worrying about dust here since the bridge will revert in that case.
        amount = _custodyTokens(token, amount);

        // Transfer the fee to the referrer.
        amount = _payFee(token, decimals, amount, feeArgs);

        // Approve the bridge to spend the tokens.
        _maxApproveIfNeeded(token, multiTokenNtt, amount);

        // Initiate the transfer.
        sequence = mtNtt.transfer{value: msg.value - executorArgs.value}(
            IMultiTokenNtt.TransferArgs(
                token, amount, recipientChain, recipient, refundAddress, false, transceiverInstructions, bytes("")
            )
        );

        // Generate the executor event.
        executor.requestExecution{value: executorArgs.value}(
            recipientChain,
            mtNtt.getPeer(recipientChain).peerAddress,
            executorArgs.refundAddress,
            executorArgs.signedQuote,
            ExecutorMessages.makeNTTv1Request(
                chainId, bytes32(uint256(uint160(address(mtNtt)))), bytes32(uint256(sequence))
            ),
            executorArgs.instructions
        );

        // Refund any excess value.
        uint256 currentBalance = address(this).balance;
        if (currentBalance > 0) {
            (bool refundSuccessful,) = payable(executorArgs.refundAddress).call{value: currentBalance}("");
            if (!refundSuccessful) {
                revert RefundFailed(currentBalance);
            }
        }
    }

    function transferETH(
        address multiTokenNtt,
        uint256 amount,
        uint16 recipientChain,
        bytes32 recipient,
        bytes32 refundAddress,
        bytes memory transceiverInstructions,
        ExecutorArgs calldata executorArgs,
        FeeArgs calldata feeArgs
    ) external payable returns (uint64 sequence) {
        IMultiTokenNtt mtNtt = IMultiTokenNtt(multiTokenNtt);
        IWETH weth = mtNtt.WETH();
        address token = address(weth);
        require(token != address(0), "WETH does not exist");
        uint8 decimals = _getDecimals(token);

        // This requires the amount + wormhole fee + executionAmount to exactly equal msg.value
        // because `transferTokensWithRelay` will revert if there is any extra.
        require(msg.value >= amount + executorArgs.value, "Not enough msg value");
        uint256 remainingValue = msg.value - (amount + executorArgs.value);

        // Trim any dust.
        amount = _trim(decimals, amount);

        // Deposit the amount to be transferred into WETH.
        weth.deposit{value: amount}();

        // Transfer the fee to the referrer.
        amount = _payFee(token, decimals, amount, feeArgs);

        // Approve the bridge to spend the tokens.
        _maxApproveIfNeeded(token, multiTokenNtt, amount);

        // Initiate the transfer.
        sequence = mtNtt.transfer{value: remainingValue}(
            IMultiTokenNtt.TransferArgs(
                token, amount, recipientChain, recipient, refundAddress, false, transceiverInstructions, bytes("")
            )
        );

        // Generate the executor event.
        executor.requestExecution{value: executorArgs.value}(
            recipientChain,
            mtNtt.getPeer(recipientChain).peerAddress,
            executorArgs.refundAddress,
            executorArgs.signedQuote,
            ExecutorMessages.makeNTTv1Request(
                chainId, bytes32(uint256(uint160(address(mtNtt)))), bytes32(uint256(sequence))
            ),
            executorArgs.instructions
        );

        // Refund any excess value.
        uint256 currentBalance = address(this).balance;
        if (currentBalance > 0) {
            (bool refundSuccessful,) = payable(executorArgs.refundAddress).call{value: currentBalance}("");
            if (!refundSuccessful) {
                revert RefundFailed(currentBalance);
            }
        }
    }

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

    // ==================== Internal Functions ==============================================

    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 _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));
    }

    // @dev The fee is calculated as a percentage of the amount being transferred.
    function _payFee(address token, uint8 decimals, uint256 amount, FeeArgs calldata feeArgs)
        internal
        returns (uint256)
    {
        uint256 fee = calculateFee(amount, feeArgs.dbps);
        fee = _trim(decimals, fee);
        if (fee > 0) {
            // Don't need to check for fee greater than or equal to amount because it can never be (since dbps is a uint16).
            amount -= fee;
            SafeERC20.safeTransfer(IERC20(token), feeArgs.payee, fee);
        }
        return amount;
    }

    function calculateFee(uint256 amount, uint16 dbps) public pure returns (uint256 fee) {
        unchecked {
            uint256 q = amount / 100000;
            uint256 r = amount % 100000;
            fee = q * dbps + (r * dbps) / 100000;
        }
    }

    function _trim(uint8 decimals, uint256 amount) internal pure returns (uint256 newFee) {
        // The prologue of `MultiTokenNtt` says the number of decimals on the local token
        // must match the number of decimals on the foreign token. So using the same value for both.
        TrimmedAmount trimmedAmount = amount.trim(decimals, decimals);
        newFee = trimmedAmount.untrim(decimals);
    }

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

    /// @dev This is based on what is in the MayanForwarder contract here: https://github.com/mayan-finance/swap-bridge/blob/main/src/MayanForwarder.sol
    function _maxApproveIfNeeded(address tokenAddr, address spender, uint256 amount) internal {
        IERC20 token = IERC20(tokenAddr);
        uint256 currentAllowance = token.allowance(address(this), spender);
        if (currentAllowance < amount) {
            SafeERC20.safeApprove(token, spender, 0);
            SafeERC20.safeApprove(token, spender, type(uint256).max);
        }
    }
}

// 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);
}

// 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");
        }
    }
}

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

interface IExecutor {
    struct SignedQuoteHeader {
        bytes4 prefix;
        address quoterAddress;
        bytes32 payeeAddress;
        uint16 srcChain;
        uint16 dstChain;
        uint64 expiryTime;
    }

    event RequestForExecution(
        address indexed quoterAddress,
        uint256 amtPaid,
        uint16 dstChain,
        bytes32 dstAddr,
        address refundAddr,
        bytes signedQuote,
        bytes requestBytes,
        bytes relayInstructions
    );

    function requestExecution(
        uint16 dstChain,
        bytes32 dstAddr,
        address refundAddr,
        bytes calldata signedQuote,
        bytes calldata requestBytes,
        bytes calldata relayInstructions
    ) external payable;
}

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

library ExecutorMessages {
    bytes4 private constant REQ_MM = "ERM1";
    bytes4 private constant REQ_VAA_V1 = "ERV1";
    bytes4 private constant REQ_NTT_V1 = "ERN1";
    bytes4 private constant REQ_CCTP_V1 = "ERC1";
    bytes4 private constant REQ_CCTP_V2 = "ERC2";

    /// @notice Payload length will not fit in a uint32.
    /// @dev Selector: 492f620d.
    error PayloadTooLarge();

    /// @notice Encodes a modular messaging request payload.
    /// @param srcChain The source chain for the message (usually this chain).
    /// @param srcAddr The source address for the message.
    /// @param sequence The sequence number returned by `endpoint.sendMessage`.
    /// @param payload The full payload, the keccak of which was sent to `endpoint.sendMessage`.
    /// @return bytes The encoded request.
    function makeMMRequest(uint16 srcChain, address srcAddr, uint64 sequence, bytes memory payload)
        internal
        pure
        returns (bytes memory)
    {
        if (payload.length > type(uint32).max) {
            revert PayloadTooLarge();
        }
        return abi.encodePacked(
            REQ_MM, srcChain, bytes32(uint256(uint160(srcAddr))), sequence, uint32(payload.length), payload
        );
    }

    /// @notice Encodes a version 1 VAA request payload.
    /// @param emitterChain The emitter chain from the VAA.
    /// @param emitterAddress The emitter address from the VAA.
    /// @param sequence The sequence number from the VAA.
    /// @return bytes The encoded request.
    function makeVAAv1Request(uint16 emitterChain, bytes32 emitterAddress, uint64 sequence)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodePacked(REQ_VAA_V1, emitterChain, emitterAddress, sequence);
    }

    /// @notice Encodes a version 1 NTT request payload.
    /// @param srcChain The source chain for the NTT transfer.
    /// @param srcManager The source manager for the NTT transfer.
    /// @param messageId The manager message id for the NTT transfer.
    /// @return bytes The encoded request.
    function makeNTTv1Request(uint16 srcChain, bytes32 srcManager, bytes32 messageId)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodePacked(REQ_NTT_V1, srcChain, srcManager, messageId);
    }

    /// @notice Encodes a version 1 CCTP request payload.
    /// @param sourceDomain The source chain for the CCTP transfer.
    /// @param nonce The nonce of the CCTP transfer.
    /// @return bytes The encoded request.
    function makeCCTPv1Request(uint32 sourceDomain, uint64 nonce) internal pure returns (bytes memory) {
        return abi.encodePacked(REQ_CCTP_V1, sourceDomain, nonce);
    }

    /// @notice Encodes a version 2 CCTP request payload.
    ///         This request currently assumes the Executor will auto detect the event off chain.
    ///         That may change in the future, in which case this interface would change.
    /// @return bytes The encoded request.
    function makeCCTPv2Request() internal pure returns (bytes memory) {
        return abi.encodePacked(REQ_CCTP_V2, uint8(1));
    }
}

// SPDX-License-Identifier: Apache 2
/// @dev TrimmedAmount is a utility library to handle token amounts with different decimals
pragma solidity >=0.8.8 <0.9.0;

import "openzeppelin-contracts/contracts/utils/math/SafeCast.sol";

/// @dev TrimmedAmount is a bit-packed representation of a token amount and its decimals.
/// @dev 64 bits: [0 - 64] amount
/// @dev 8 bits: [64 - 72] decimals
type TrimmedAmount is uint72;

using {gt as >, lt as <, sub as -, add as +, eq as ==, min, unwrap} for TrimmedAmount global;

function minUint8(uint8 a, uint8 b) pure returns (uint8) {
    return a < b ? a : b;
}

/// @notice Error when the decimals of two TrimmedAmounts are not equal
/// @dev Selector. b9cdb6c2
/// @param decimals the decimals of the first TrimmedAmount
/// @param decimalsOther the decimals of the second TrimmedAmount
error NumberOfDecimalsNotEqual(uint8 decimals, uint8 decimalsOther);

uint8 constant TRIMMED_DECIMALS = 8;

function unwrap(
    TrimmedAmount a
) pure returns (uint72) {
    return TrimmedAmount.unwrap(a);
}

function packTrimmedAmount(uint64 amt, uint8 decimals) pure returns (TrimmedAmount) {
    // cast to u72 first to prevent overflow
    uint72 amount = uint72(amt);
    uint72 dec = uint72(decimals);

    // shift the amount to the left 8 bits
    amount <<= 8;

    return TrimmedAmount.wrap(amount | dec);
}

function eq(TrimmedAmount a, TrimmedAmount b) pure returns (bool) {
    return TrimmedAmountLib.getAmount(a) == TrimmedAmountLib.getAmount(b)
        && TrimmedAmountLib.getDecimals(a) == TrimmedAmountLib.getDecimals(b);
}

function checkDecimals(TrimmedAmount a, TrimmedAmount b) pure {
    uint8 aDecimals = TrimmedAmountLib.getDecimals(a);
    uint8 bDecimals = TrimmedAmountLib.getDecimals(b);
    if (aDecimals != bDecimals) {
        revert NumberOfDecimalsNotEqual(aDecimals, bDecimals);
    }
}

function gt(TrimmedAmount a, TrimmedAmount b) pure returns (bool) {
    checkDecimals(a, b);

    return TrimmedAmountLib.getAmount(a) > TrimmedAmountLib.getAmount(b);
}

function lt(TrimmedAmount a, TrimmedAmount b) pure returns (bool) {
    checkDecimals(a, b);

    return TrimmedAmountLib.getAmount(a) < TrimmedAmountLib.getAmount(b);
}

function sub(TrimmedAmount a, TrimmedAmount b) pure returns (TrimmedAmount) {
    checkDecimals(a, b);

    return packTrimmedAmount(
        TrimmedAmountLib.getAmount(a) - TrimmedAmountLib.getAmount(b),
        TrimmedAmountLib.getDecimals(a)
    );
}

function add(TrimmedAmount a, TrimmedAmount b) pure returns (TrimmedAmount) {
    checkDecimals(a, b);

    return packTrimmedAmount(
        TrimmedAmountLib.getAmount(a) + TrimmedAmountLib.getAmount(b),
        TrimmedAmountLib.getDecimals(b)
    );
}

function min(TrimmedAmount a, TrimmedAmount b) pure returns (TrimmedAmount) {
    checkDecimals(a, b);

    return TrimmedAmountLib.getAmount(a) < TrimmedAmountLib.getAmount(b) ? a : b;
}

library TrimmedAmountLib {
    /// @notice Error when the amount to be trimmed is greater than u64MAX.
    /// @dev Selector 0x08083b2a.
    /// @param amount The amount to be trimmed.
    error AmountTooLarge(uint256 amount);

    function getAmount(
        TrimmedAmount a
    ) internal pure returns (uint64) {
        // Extract the raw integer value from TrimmedAmount
        uint72 rawValue = TrimmedAmount.unwrap(a);

        // Right shift to keep only the higher 64 bits
        uint64 result = uint64(rawValue >> 8);
        return result;
    }

    function getDecimals(
        TrimmedAmount a
    ) internal pure returns (uint8) {
        return uint8(TrimmedAmount.unwrap(a) & 0xFF);
    }

    /// @dev Set the decimals of the TrimmedAmount.
    ///      This function should only be used for testing purposes, as it
    ///      should not be necessary to change the decimals of a TrimmedAmount
    ///      under normal circumstances.
    function setDecimals(TrimmedAmount a, uint8 decimals) internal pure returns (TrimmedAmount) {
        return TrimmedAmount.wrap((TrimmedAmount.unwrap(a) & ~uint72(0xFF)) | decimals);
    }

    function isNull(
        TrimmedAmount a
    ) internal pure returns (bool) {
        return (getAmount(a) == 0 && getDecimals(a) == 0);
    }

    function saturatingAdd(
        TrimmedAmount a,
        TrimmedAmount b
    ) internal pure returns (TrimmedAmount) {
        checkDecimals(a, b);

        uint256 saturatedSum;
        uint64 aAmount = getAmount(a);
        uint64 bAmount = getAmount(b);
        unchecked {
            saturatedSum = uint256(aAmount) + uint256(bAmount);
            saturatedSum = saturatedSum > type(uint64).max ? type(uint64).max : saturatedSum;
        }

        return packTrimmedAmount(SafeCast.toUint64(saturatedSum), getDecimals(a));
    }

    /// @dev scale the amount from original decimals to target decimals (base 10)
    function scale(
        uint256 amount,
        uint8 fromDecimals,
        uint8 toDecimals
    ) internal pure returns (uint256) {
        if (fromDecimals == toDecimals) {
            return amount;
        }

        if (fromDecimals > toDecimals) {
            return amount / (10 ** (fromDecimals - toDecimals));
        } else {
            return amount * (10 ** (toDecimals - fromDecimals));
        }
    }

    function shift(TrimmedAmount amount, uint8 toDecimals) internal pure returns (TrimmedAmount) {
        uint8 actualToDecimals = minUint8(TRIMMED_DECIMALS, toDecimals);
        return packTrimmedAmount(
            SafeCast.toUint64(scale(getAmount(amount), getDecimals(amount), actualToDecimals)),
            actualToDecimals
        );
    }

    function max(
        uint8 decimals
    ) internal pure returns (TrimmedAmount) {
        uint8 actualDecimals = minUint8(TRIMMED_DECIMALS, decimals);
        return packTrimmedAmount(type(uint64).max, actualDecimals);
    }

    /// @dev trim the amount to target decimals.
    ///      The actual resulting decimals is the minimum of TRIMMED_DECIMALS,
    ///      fromDecimals, and toDecimals. This ensures that no dust is
    ///      destroyed on either side of the transfer.
    /// @param amt the amount to be trimmed
    /// @param fromDecimals the original decimals of the amount
    /// @param toDecimals the target decimals of the amount
    /// @return TrimmedAmount uint72 value type bit-packed with decimals
    function trim(
        uint256 amt,
        uint8 fromDecimals,
        uint8 toDecimals
    ) internal pure returns (TrimmedAmount) {
        uint8 actualToDecimals = minUint8(minUint8(TRIMMED_DECIMALS, fromDecimals), toDecimals);
        uint256 amountScaled = scale(amt, fromDecimals, actualToDecimals);

        // NOTE: amt after trimming must fit into uint64 (that's the point of
        // trimming, as Solana only supports uint64 for token amts)
        return packTrimmedAmount(SafeCast.toUint64(amountScaled), actualToDecimals);
    }

    function untrim(TrimmedAmount amt, uint8 toDecimals) internal pure returns (uint256) {
        uint256 deNorm = uint256(getAmount(amt));
        uint8 fromDecimals = getDecimals(amt);
        uint256 amountScaled = scale(deNorm, fromDecimals, toDecimals);

        return amountScaled;
    }
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

import "./IWETH.sol";

/// @notice This is based on the Monad Bridge MultiTokenNtt contract as defined here: https://github.com/wormholelabs-xyz/Monad-Bridge/blob/multi-token/evm/src/MultiTokenNtt/MultiTokenNtt.sol
///         We only define what is used by `MultiTokenNttWithExecutor`.
interface IMultiTokenNtt {
    /// @notice Transfer tokens to another chain with comprehensive parameter support
    struct TransferArgs {
        address token;
        uint256 amount;
        uint16 recipientChain;
        bytes32 recipient;
        bytes32 refundAddress;
        bool shouldQueue;
        bytes transceiverInstructions;
        bytes additionalPayload;
    }

    function transfer(TransferArgs memory args) external payable returns (uint64);

    struct Peer {
        bytes32 peerAddress;
    }

    function getPeer(uint16 chainId_) external view returns (Peer memory);
    function WETH() external returns (IWETH);
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;

struct ExecutorArgs {
    // The msg value to be passed into the Executor.
    uint256 value;
    // The refund address used by the Executor.
    address refundAddress;
    // The signed quote to be passed into the Executor.
    bytes signedQuote;
    // The relay instructions to be passed into the Executor.
    bytes instructions;
}

struct FeeArgs {
    // The fee in tenths of basis points.
    uint16 dbps;
    // To whom the fee should be paid (the "referrer").
    address payee;
}

interface IMultiTokenNttWithExecutor {
    /// @notice Error when the refund to the sender fails.
    /// @dev Selector 0x2ca23714.
    /// @param refundAmount The refund amount.
    error RefundFailed(uint256 refundAmount);

    function transfer(
        address multiTokenNtt,
        address token,
        uint256 amount,
        uint16 recipientChain,
        bytes32 recipient,
        bytes32 refundAddress,
        bytes memory transceiverInstructions,
        ExecutorArgs calldata executorArgs,
        FeeArgs calldata feeArgs
    ) external payable returns (uint64);

    function transferETH(
        address multiTokenNtt,
        uint256 amount,
        uint16 recipientChain,
        bytes32 recipient,
        bytes32 refundAddress,
        bytes memory transceiverInstructions,
        ExecutorArgs calldata executorArgs,
        FeeArgs calldata feeArgs
    ) external payable returns (uint64);
}

// 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);
}

// 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 11 of 12 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.17;

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

interface IWETH is IERC20 {
    function deposit() external payable;

    function transfer(address to, uint256 value) external returns (bool);

    function withdraw(uint256) external;
}

Settings
{
  "remappings": [
    "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
    "example-messaging-executor/=lib/example-messaging-executor/",
    "forge-std/=lib/forge-std/src/",
    "native-token-transfers/=lib/native-token-transfers/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solidity-bytes-utils/=lib/native-token-transfers/evm/lib/solidity-bytes-utils/contracts/",
    "wormhole-solidity-sdk/=lib/native-token-transfers/evm/lib/wormhole-solidity-sdk/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": true
}

Contract ABI

API
[{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"address","name":"_executor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"refundAmount","type":"uint256"}],"name":"RefundFailed","type":"error"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"dbps","type":"uint16"}],"name":"calculateFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executor","outputs":[{"internalType":"contract IExecutor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"multiTokenNtt","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"recipientChain","type":"uint16"},{"internalType":"bytes32","name":"recipient","type":"bytes32"},{"internalType":"bytes32","name":"refundAddress","type":"bytes32"},{"internalType":"bytes","name":"transceiverInstructions","type":"bytes"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"},{"internalType":"bytes","name":"signedQuote","type":"bytes"},{"internalType":"bytes","name":"instructions","type":"bytes"}],"internalType":"struct ExecutorArgs","name":"executorArgs","type":"tuple"},{"components":[{"internalType":"uint16","name":"dbps","type":"uint16"},{"internalType":"address","name":"payee","type":"address"}],"internalType":"struct FeeArgs","name":"feeArgs","type":"tuple"}],"name":"transfer","outputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"multiTokenNtt","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"recipientChain","type":"uint16"},{"internalType":"bytes32","name":"recipient","type":"bytes32"},{"internalType":"bytes32","name":"refundAddress","type":"bytes32"},{"internalType":"bytes","name":"transceiverInstructions","type":"bytes"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"},{"internalType":"bytes","name":"signedQuote","type":"bytes"},{"internalType":"bytes","name":"instructions","type":"bytes"}],"internalType":"struct ExecutorArgs","name":"executorArgs","type":"tuple"},{"components":[{"internalType":"uint16","name":"dbps","type":"uint16"},{"internalType":"address","name":"payee","type":"address"}],"internalType":"struct FeeArgs","name":"feeArgs","type":"tuple"}],"name":"transferETH","outputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c0346100b457601f61146138819003918201601f19168301916001600160401b038311848410176100b95780849260409485528339810103126100b457805161ffff8116918282036100b457602001516001600160a01b03811692908390036100b45761006e9015156100cf565b6100798215156100cf565b60805260a05260405161137490816100ed82396080518181816103b701526106ad015260a05181818160e60152818161034001526108b80152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b156100d657565b634e487b7160e01b600052600160045260246000fdfe6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c80630fed70a214610a51578063924105c3146106d15780639a8a059214610692578063be2fa91014610115578063c34c08e5146100d05763ffa1ad7414610069575061000e565b346100cd57806003193601126100cd57506100c960405161008b604082610ae7565b601f81527f4d756c7469546f6b656e4e7474576974684578656375746f722d302e302e31006020820152604051918291602083526020830190610b6a565b0390f35b80fd5b50346100cd57806003193601126100cd576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b506101203660031901126100cd5761012b610a9a565b906024356044359161ffff83168084036104935760a4356001600160401b03811161068e5761015e903690600401610b23565b9360c435916001600160401b03831161068a578260040191608060031985360301126106865760403660e3190112610686576040516315ab88c960e31b81526001600160a01b03891696906020816004818a8c5af190811561050d578791610640575b506001600160a01b0316978815610605576101db89610d9a565b988535926101e98482610d8d565b34106105c9576102278b610211818061020b6102058a88610d8d565b34610bab565b95611067565b6001600160401b0360ff82169160081c1661122f565b823b156105ba57604051630d0e30db60e41b81528a8160048185885af180156105be57908b916105a5575b5050809b60e43561ffff811681036104a25790610211818061028961028e95879061ffff16620186a0808281850602049204020190565b611067565b9081610518575b50506102ab8b809d6103159a9b9c9d5084610dea565b60209b8c93604051916102be8684610ae7565b8c8352604051946102ce86610ab5565b855285850152876040850152606435606085015260843560808501528b60a085015260c084015260e083015260405180809981946329185d6160e21b835260048301610bed565b03918c5af194851561050d5787956104de575b50604051630c128d1760e41b815260048101939093527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169289816024818c5afa9081156104d35788916104a6575b50519160248701966001600160401b036103e361039b8a610ca0565b9760646103db6103ae6044870184610cb4565b95909c169e8f907f0000000000000000000000000000000000000000000000000000000000000000610fdb565b940190610cb4565b929091873b156104a257918b98979695949391610417936040519b8c9a8b998a9863c513d43760e01b8a5260048a01610d07565b03925af180156104975790839161047e575b505047908161043e575b505050604051908152f35b82808084819461045460018060a01b0391610ca0565b165af161045f610d5d565b501561046b5780610433565b630b288dc560e21b825260045260249150fd5b8161048891610ae7565b610493578138610429565b5080fd5b6040513d85823e3d90fd5b8b80fd5b6104c691508a3d8c116104cc575b6104be8183610ae7565b810190610c72565b3861037f565b503d6104b4565b6040513d8a823e3d90fd5b6104ff919550893d8b11610506575b6104f78183610ae7565b810190610bce565b9338610328565b503d6104ed565b6040513d89823e3d90fd5b819c509061052591610bab565b9a610104356001600160a01b03811681036105a15760405163a9059cbb60e01b60208201526001600160a01b03909116602482015260448101919091529a9b999a98999798610315986102ab918e91906105969061059081606481015b03601f198101835282610ae7565b86611122565b9d9c9b9a9950610295565b8a80fd5b816105af91610ae7565b6105ba578938610252565b8980fd5b6040513d8d823e3d90fd5b60405162461bcd60e51b81526020600482015260146024820152734e6f7420656e6f756768206d73672076616c756560601b6044820152606490fd5b60405162461bcd60e51b815260206004820152601360248201527215d1551208191bd95cc81b9bdd08195e1a5cdd606a1b6044820152606490fd5b90506020813d60201161067e575b8161065b60209383610ae7565b8101031261067a57516001600160a01b038116810361067a57386101c1565b8680fd5b3d915061064e565b8480fd5b8380fd5b8280fd5b50346100cd57806003193601126100cd57602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b506101403660031901126100cd576106e7610a9a565b602435916001600160a01b038316908184036100cd576064359061ffff8216928383036104935760c4356001600160401b03811161068e5761072d903690600401610b23565b9360e435936001600160401b03851161068a5784600401926080600319873603011261068657604036610103190112610686576001600160a01b038816966107748a610d9a565b986107c56107818c611017565b6107b76040516323b872dd60e01b6020820152336024820152306044820152604435606482015260648152610590608482610ae7565b6107c08d611017565b610bab565b996101043561ffff81168103610a4d579061021181806102898f956107fb969061ffff16620186a0808281850602049204020190565b806109cc575b508961081691819c61088d999a9b9c50610dea565b8435916108238334610bab565b60209b8c93604051916108368684610ae7565b8b83526040519461084686610ab5565b855285850152876040850152608435606085015260a43560808501528a60a085015260c084015260e083015260405180809981946329185d6160e21b835260048301610bed565b03918c5af19485156109c15786956109a2575b50604051630c128d1760e41b815260048101939093527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169289816024818c5afa90811561050d578791610985575b50519160248801976001600160401b0361091361039b8b610ca0565b929091873b156105a157918a98979695949391610947936040519b8c9a8b998a9863c513d43760e01b8a5260048a01610d07565b03925af1801561097a5761096a575b509047908161043e57505050604051908152f35b8161097491610ae7565b38610956565b6040513d84823e3d90fd5b61099c91508a3d8c116104cc576104be8183610ae7565b386108f7565b6109ba919550893d8b11610506576104f78183610ae7565b93386108a0565b6040513d88823e3d90fd5b998a6109d791610bab565b99610124356001600160a01b0381168103610a4d5760405163a9059cbb60e01b60208201526001600160a01b0390911660248201526044810191909152999a98999798969761088d97610816928d92909190610a4090610a3a8160648101610582565b87611122565b9c9b9a9998509150610801565b8880fd5b50346100cd5760403660031901126100cd576024359061ffff821682036100cd576020610a92836004359061ffff16620186a0808281850602049204020190565b604051908152f35b600435906001600160a01b0382168203610ab057565b600080fd5b61010081019081106001600160401b03821117610ad157604052565b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b03821117610ad157604052565b6001600160401b038111610ad157601f01601f191660200190565b81601f82011215610ab057803590610b3a82610b08565b92610b486040519485610ae7565b82845260208383010111610ab057816000926020809301838601378301015290565b919082519283825260005b848110610b96575050826000602080949584010152601f8019910116010190565b80602080928401015182828601015201610b75565b91908203918211610bb857565b634e487b7160e01b600052601160045260246000fd5b90816020910312610ab057516001600160401b0381168103610ab05790565b90610c6f916020815260018060a01b0382511660208201526020820151604082015261ffff604083015116606082015260608201516080820152608082015160a082015260a0820151151560c082015260e0610c5960c084015161010083850152610120840190610b6a565b92015190610100601f1982850301910152610b6a565b90565b90816020910312610ab05760405190602082018281106001600160401b03821117610ad15760405251815290565b356001600160a01b0381168103610ab05790565b903590601e1981360301821215610ab057018035906001600160401b038211610ab057602001918136038313610ab057565b908060209392818452848401376000828201840152601f01601f1916010190565b9694610c6f989693610d419361ffff610d4f9794168a5260208a015260018060a01b0316604089015260c0606089015260c0880191610ce6565b908582036080870152610b6a565b9260a0818503910152610ce6565b3d15610d88573d90610d6e82610b08565b91610d7c6040519384610ae7565b82523d6000602084013e565b606090565b91908201809211610bb857565b60008091604051602081019063313ce56760e01b825260048152610dbf602482610ae7565b51915afa50610dcc610d5d565b602081805181010312610ab0576020015160ff81168103610ab05790565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301529190911692602082604481875afa8015610fcf576000928391610f9d575b5010610e3657505050565b5060405163095ea7b360e01b60208201526001600160a01b03821660248201819052600060448084019190915282529190610e7c90610e76606482610ae7565b84611122565b604051636eb1769f60e11b81523060048201526001600160a01b03919091166024820152600090602081604481875afa918215610f91578092610f5c575b5050610ef857610ef6916040519163095ea7b360e01b60208401526024830152600019604483015260448252610ef1606483610ae7565b611122565b565b60405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608490fd5b9091506020823d602011610f89575b81610f7860209383610ae7565b810103126100cd5750513880610eba565b3d9150610f6b565b604051903d90823e3d90fd5b90506020813d602011610fc7575b81610fb860209383610ae7565b8101031261068e575138610e2b565b3d9150610fab565b6040513d6000823e3d90fd5b9190604051926345524e3160e01b602085015261ffff60f01b9060f01b1660248401526026830152604682015260468152610c6f606682610ae7565b6000809160405160208101906370a0823160e01b825230602482015260248152611042604482610ae7565b51915afa5061104f610d5d565b60208151918180820193849201010312610ab0575190565b611097919260ff841660081060001461111b576008905b60ff811660ff831610600014611111575092839161122f565b906001600160401b0382116110bd5760ff68ffffffffffffffff0091169160081b161790565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608490fd5b905092839161122f565b839061107e565b604080519092611187926001600160a01b03169060009081906111458786610ae7565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af1611181610d5d565b916112a1565b80518061119357505050565b8160209181010312610ab05760200151801590811503610ab0576111b45750565b5162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b9060ff8091169116039060ff8211610bb857565b60ff16604d8111610bb857600a0a90565b919060ff821660ff821681811461129a57111561127957611258916112539161120a565b61121e565b908115611263570490565b634e487b7160e01b600052601260045260246000fd5b611253906112869261120a565b90818102918183041490151715610bb85790565b5050505090565b9192901561130357508151156112b5575090565b3b156112be5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156113165750805190602001fd5b60405162461bcd60e51b81526020600482015290819061133a906024830190610b6a565b0390fdfea264697066735822122067d4d22d723954e2140f731b0a94c823f4a7f092172f707777021c43381dec3e64736f6c634300081c00330000000000000000000000000000000000000000000000000000000000002712000000000000000000000000d0fb39f5a3361f21457653cb70f9d0c9bd86b66b

Deployed Bytecode

0x6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c80630fed70a214610a51578063924105c3146106d15780639a8a059214610692578063be2fa91014610115578063c34c08e5146100d05763ffa1ad7414610069575061000e565b346100cd57806003193601126100cd57506100c960405161008b604082610ae7565b601f81527f4d756c7469546f6b656e4e7474576974684578656375746f722d302e302e31006020820152604051918291602083526020830190610b6a565b0390f35b80fd5b50346100cd57806003193601126100cd576040517f000000000000000000000000d0fb39f5a3361f21457653cb70f9d0c9bd86b66b6001600160a01b03168152602090f35b506101203660031901126100cd5761012b610a9a565b906024356044359161ffff83168084036104935760a4356001600160401b03811161068e5761015e903690600401610b23565b9360c435916001600160401b03831161068a578260040191608060031985360301126106865760403660e3190112610686576040516315ab88c960e31b81526001600160a01b03891696906020816004818a8c5af190811561050d578791610640575b506001600160a01b0316978815610605576101db89610d9a565b988535926101e98482610d8d565b34106105c9576102278b610211818061020b6102058a88610d8d565b34610bab565b95611067565b6001600160401b0360ff82169160081c1661122f565b823b156105ba57604051630d0e30db60e41b81528a8160048185885af180156105be57908b916105a5575b5050809b60e43561ffff811681036104a25790610211818061028961028e95879061ffff16620186a0808281850602049204020190565b611067565b9081610518575b50506102ab8b809d6103159a9b9c9d5084610dea565b60209b8c93604051916102be8684610ae7565b8c8352604051946102ce86610ab5565b855285850152876040850152606435606085015260843560808501528b60a085015260c084015260e083015260405180809981946329185d6160e21b835260048301610bed565b03918c5af194851561050d5787956104de575b50604051630c128d1760e41b815260048101939093527f000000000000000000000000d0fb39f5a3361f21457653cb70f9d0c9bd86b66b6001600160a01b03169289816024818c5afa9081156104d35788916104a6575b50519160248701966001600160401b036103e361039b8a610ca0565b9760646103db6103ae6044870184610cb4565b95909c169e8f907f0000000000000000000000000000000000000000000000000000000000002712610fdb565b940190610cb4565b929091873b156104a257918b98979695949391610417936040519b8c9a8b998a9863c513d43760e01b8a5260048a01610d07565b03925af180156104975790839161047e575b505047908161043e575b505050604051908152f35b82808084819461045460018060a01b0391610ca0565b165af161045f610d5d565b501561046b5780610433565b630b288dc560e21b825260045260249150fd5b8161048891610ae7565b610493578138610429565b5080fd5b6040513d85823e3d90fd5b8b80fd5b6104c691508a3d8c116104cc575b6104be8183610ae7565b810190610c72565b3861037f565b503d6104b4565b6040513d8a823e3d90fd5b6104ff919550893d8b11610506575b6104f78183610ae7565b810190610bce565b9338610328565b503d6104ed565b6040513d89823e3d90fd5b819c509061052591610bab565b9a610104356001600160a01b03811681036105a15760405163a9059cbb60e01b60208201526001600160a01b03909116602482015260448101919091529a9b999a98999798610315986102ab918e91906105969061059081606481015b03601f198101835282610ae7565b86611122565b9d9c9b9a9950610295565b8a80fd5b816105af91610ae7565b6105ba578938610252565b8980fd5b6040513d8d823e3d90fd5b60405162461bcd60e51b81526020600482015260146024820152734e6f7420656e6f756768206d73672076616c756560601b6044820152606490fd5b60405162461bcd60e51b815260206004820152601360248201527215d1551208191bd95cc81b9bdd08195e1a5cdd606a1b6044820152606490fd5b90506020813d60201161067e575b8161065b60209383610ae7565b8101031261067a57516001600160a01b038116810361067a57386101c1565b8680fd5b3d915061064e565b8480fd5b8380fd5b8280fd5b50346100cd57806003193601126100cd57602060405161ffff7f0000000000000000000000000000000000000000000000000000000000002712168152f35b506101403660031901126100cd576106e7610a9a565b602435916001600160a01b038316908184036100cd576064359061ffff8216928383036104935760c4356001600160401b03811161068e5761072d903690600401610b23565b9360e435936001600160401b03851161068a5784600401926080600319873603011261068657604036610103190112610686576001600160a01b038816966107748a610d9a565b986107c56107818c611017565b6107b76040516323b872dd60e01b6020820152336024820152306044820152604435606482015260648152610590608482610ae7565b6107c08d611017565b610bab565b996101043561ffff81168103610a4d579061021181806102898f956107fb969061ffff16620186a0808281850602049204020190565b806109cc575b508961081691819c61088d999a9b9c50610dea565b8435916108238334610bab565b60209b8c93604051916108368684610ae7565b8b83526040519461084686610ab5565b855285850152876040850152608435606085015260a43560808501528a60a085015260c084015260e083015260405180809981946329185d6160e21b835260048301610bed565b03918c5af19485156109c15786956109a2575b50604051630c128d1760e41b815260048101939093527f000000000000000000000000d0fb39f5a3361f21457653cb70f9d0c9bd86b66b6001600160a01b03169289816024818c5afa90811561050d578791610985575b50519160248801976001600160401b0361091361039b8b610ca0565b929091873b156105a157918a98979695949391610947936040519b8c9a8b998a9863c513d43760e01b8a5260048a01610d07565b03925af1801561097a5761096a575b509047908161043e57505050604051908152f35b8161097491610ae7565b38610956565b6040513d84823e3d90fd5b61099c91508a3d8c116104cc576104be8183610ae7565b386108f7565b6109ba919550893d8b11610506576104f78183610ae7565b93386108a0565b6040513d88823e3d90fd5b998a6109d791610bab565b99610124356001600160a01b0381168103610a4d5760405163a9059cbb60e01b60208201526001600160a01b0390911660248201526044810191909152999a98999798969761088d97610816928d92909190610a4090610a3a8160648101610582565b87611122565b9c9b9a9998509150610801565b8880fd5b50346100cd5760403660031901126100cd576024359061ffff821682036100cd576020610a92836004359061ffff16620186a0808281850602049204020190565b604051908152f35b600435906001600160a01b0382168203610ab057565b600080fd5b61010081019081106001600160401b03821117610ad157604052565b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b03821117610ad157604052565b6001600160401b038111610ad157601f01601f191660200190565b81601f82011215610ab057803590610b3a82610b08565b92610b486040519485610ae7565b82845260208383010111610ab057816000926020809301838601378301015290565b919082519283825260005b848110610b96575050826000602080949584010152601f8019910116010190565b80602080928401015182828601015201610b75565b91908203918211610bb857565b634e487b7160e01b600052601160045260246000fd5b90816020910312610ab057516001600160401b0381168103610ab05790565b90610c6f916020815260018060a01b0382511660208201526020820151604082015261ffff604083015116606082015260608201516080820152608082015160a082015260a0820151151560c082015260e0610c5960c084015161010083850152610120840190610b6a565b92015190610100601f1982850301910152610b6a565b90565b90816020910312610ab05760405190602082018281106001600160401b03821117610ad15760405251815290565b356001600160a01b0381168103610ab05790565b903590601e1981360301821215610ab057018035906001600160401b038211610ab057602001918136038313610ab057565b908060209392818452848401376000828201840152601f01601f1916010190565b9694610c6f989693610d419361ffff610d4f9794168a5260208a015260018060a01b0316604089015260c0606089015260c0880191610ce6565b908582036080870152610b6a565b9260a0818503910152610ce6565b3d15610d88573d90610d6e82610b08565b91610d7c6040519384610ae7565b82523d6000602084013e565b606090565b91908201809211610bb857565b60008091604051602081019063313ce56760e01b825260048152610dbf602482610ae7565b51915afa50610dcc610d5d565b602081805181010312610ab0576020015160ff81168103610ab05790565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301529190911692602082604481875afa8015610fcf576000928391610f9d575b5010610e3657505050565b5060405163095ea7b360e01b60208201526001600160a01b03821660248201819052600060448084019190915282529190610e7c90610e76606482610ae7565b84611122565b604051636eb1769f60e11b81523060048201526001600160a01b03919091166024820152600090602081604481875afa918215610f91578092610f5c575b5050610ef857610ef6916040519163095ea7b360e01b60208401526024830152600019604483015260448252610ef1606483610ae7565b611122565b565b60405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608490fd5b9091506020823d602011610f89575b81610f7860209383610ae7565b810103126100cd5750513880610eba565b3d9150610f6b565b604051903d90823e3d90fd5b90506020813d602011610fc7575b81610fb860209383610ae7565b8101031261068e575138610e2b565b3d9150610fab565b6040513d6000823e3d90fd5b9190604051926345524e3160e01b602085015261ffff60f01b9060f01b1660248401526026830152604682015260468152610c6f606682610ae7565b6000809160405160208101906370a0823160e01b825230602482015260248152611042604482610ae7565b51915afa5061104f610d5d565b60208151918180820193849201010312610ab0575190565b611097919260ff841660081060001461111b576008905b60ff811660ff831610600014611111575092839161122f565b906001600160401b0382116110bd5760ff68ffffffffffffffff0091169160081b161790565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608490fd5b905092839161122f565b839061107e565b604080519092611187926001600160a01b03169060009081906111458786610ae7565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af1611181610d5d565b916112a1565b80518061119357505050565b8160209181010312610ab05760200151801590811503610ab0576111b45750565b5162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b9060ff8091169116039060ff8211610bb857565b60ff16604d8111610bb857600a0a90565b919060ff821660ff821681811461129a57111561127957611258916112539161120a565b61121e565b908115611263570490565b634e487b7160e01b600052601260045260246000fd5b611253906112869261120a565b90818102918183041490151715610bb85790565b5050505090565b9192901561130357508151156112b5575090565b3b156112be5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156113165750805190602001fd5b60405162461bcd60e51b81526020600482015290819061133a906024830190610b6a565b0390fdfea264697066735822122067d4d22d723954e2140f731b0a94c823f4a7f092172f707777021c43381dec3e64736f6c634300081c0033

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

0000000000000000000000000000000000000000000000000000000000002712000000000000000000000000d0fb39f5a3361f21457653cb70f9d0c9bd86b66b

-----Decoded View---------------
Arg [0] : _chainId (uint16): 10002
Arg [1] : _executor (address): 0xD0fb39f5a3361F21457653cB70F9D0C9bD86B66B

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000002712
Arg [1] : 000000000000000000000000d0fb39f5a3361f21457653cb70f9d0c9bd86b66b


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
0x70b1CD25Aa1DEbEf2BCa0eDbc11228C5EB4dAD0F
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.