ETH Price: $1,968.22 (-0.63%)

Transaction Decoder

Block:
23123508 at Aug-12-2025 07:35:11 AM +UTC
Transaction Fee:
0.000107300982264504 ETH $0.21
Gas Used:
263,928 Gas / 0.406553993 Gwei

Emitted Events:

124 0xe7ae30c03395d66f30a26c49c91edae151747911.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x000000000000000000000000d493066498ace409059fda4c1bcd2e73d8cffe01, 0x000000000000000000000000d2d9c936165a85f27a5a7e07afb974d022b89463, 0000000000000000000000000000000000000000000000000000002e90edd000 )
125 0xe7ae30c03395d66f30a26c49c91edae151747911.0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925( 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925, 0x000000000000000000000000d2d9c936165a85f27a5a7e07afb974d022b89463, 0x00000000000000000000000064e4b81023621cb08f5ac305c2dd6edaad717834, 0000000000000000000000000000000000000000000000000000002e90edd000 )
126 0xe7ae30c03395d66f30a26c49c91edae151747911.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x000000000000000000000000d2d9c936165a85f27a5a7e07afb974d022b89463, 0x00000000000000000000000064e4b81023621cb08f5ac305c2dd6edaad717834, 0000000000000000000000000000000000000000000000000000002e90edd000 )
127 0xe7ae30c03395d66f30a26c49c91edae151747911.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000064e4b81023621cb08f5ac305c2dd6edaad717834, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000002e90edd000 )
128 Wormhole.0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2( 0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2, 0x000000000000000000000000454f5cf9143cda1291eb80dcbbcdfab4544e0920, 0000000000000000000000000000000000000000000000000000000000000004, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000080, 00000000000000000000000000000000000000000000000000000000000000ca, 00000000000000000000000000000000000000000000000000000000000000d9, 9945ff1000000000000000000000000064e4b81023621cb08f5ac305c2dd6eda, ad717834000000000000000000000000429410525068b694160d686eacf72ce1, 2b66599100910000000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000d2d9c936165a85f27a5a7e07afb9, 74d022b89463004f994e54540800000000000000140000000000000000000000, 00e7ae30c03395d66f30a26c49c91edae1517479110000000000000000000000, 00d493066498ace409059fda4c1bcd2e73d8cffe01001e000000000000000000 )
129 0x454f5cf9143cda1291eb80dcbbcdfab4544e0920.0xc3192e083c87c556db539f071d8a298869f487e951327b5616a6f85ae3da958e( 0xc3192e083c87c556db539f071d8a298869f487e951327b5616a6f85ae3da958e, 0000000000000000000000000000000000000000000000000000000000000002, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
130 0x454f5cf9143cda1291eb80dcbbcdfab4544e0920.0x79376a0dc6cbfe6f6f8f89ad24c262a8c6233f8df181d3fe5abb2e2442e8c738( 0x79376a0dc6cbfe6f6f8f89ad24c262a8c6233f8df181d3fe5abb2e2442e8c738, 000000000000000000000000000000000000000000000000000000000000001e, 0000000000000000000000000000000000000000000000000000000000000040, 00000000000000000000000064e4b81023621cb08f5ac305c2dd6edaad717834, 000000000000000000000000429410525068b694160d686eacf72ce12b665991, 0000000000000000000000000000000000000000000000000000000000000080, 0000000000000000000000000000000000000000000000000000000000000140, 0000000000000000000000000000000000000000000000000000000000000091, 0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000d2d9c936165a85f27a5a7e07afb974d022b89463, 004f994e5454080000000000000014000000000000000000000000e7ae30c033, 95d66f30a26c49c91edae151747911000000000000000000000000d493066498, ace409059fda4c1bcd2e73d8cffe01001e000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
131 0x64e4b81023621cb08f5ac305c2dd6edaad717834.0xe54e51e42099622516fa3b48e9733581c9dbdcb771cafb093f745a0532a35982( 0xe54e51e42099622516fa3b48e9733581c9dbdcb771cafb093f745a0532a35982, 0x000000000000000000000000d493066498ace409059fda4c1bcd2e73d8cffe01, 0x000000000000000000000000d493066498ace409059fda4c1bcd2e73d8cffe01, 0000000000000000000000000000000000000000000000000000002e90edd000, 0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000000000000000000001e, 0000000000000000000000000000000000000000000000000000000000000000 )
132 0x64e4b81023621cb08f5ac305c2dd6edaad717834.0x3e6ae56314c6da8b461d872f41c6d0bb69317b9d0232805aaccfa45df1a16fa0( 0x3e6ae56314c6da8b461d872f41c6d0bb69317b9d0232805aaccfa45df1a16fa0, 0x20ddcbd022cb4af30c31cb1d454c42504d9a67eefa47b85df92e42315da44a77 )
133 Executor.RequestForExecution( quoterAddress=0xa5400801...E2b133596, amtPaid=24858336000000, dstChain=30, dstAddr=000000000000000000000000429410525068B694160D686EACF72CE12B665991, refundAddr=[Sender] 0xd493066498ace409059fda4c1bcd2e73d8cffe01, signedQuote=0x45513031A54008017941ECE968623A0DD8EE907E2B1335960000000000000000000000006A8BFC410A3CC7306D52872F116AFB12F1CEC6C60002001E00000000689AFCA600000000000389B700000000003306C800002739B4CDB80000002739B4CDB800BB9F0EDBB011387C1F0C9EC019461839C651191AE129B95262A22C30B16F258172E75B1A9A34B71AB376E14267816338E67B64C01B5068BCB539D3CB4A527F6B1C, requestBytes=0x45524E31000200000000000000000000000064E4B81023621CB08F5AC305C2DD6EDAAD7178340000000000000000000000000000000000000000000000000000000000000000, relayInstructions=0x010000000000000000000000000007A12000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
(Lido: Execution Layer Rewards Vault)
45.582088061193801806 Eth45.582108911505801806 Eth0.000020850312
0x64E4b810...aaD717834
0x6a8BFC41...2F1cec6C6 0.899402461032826408 Eth0.899427319368826408 Eth0.000024858336
0x98f3c9e6...f1464288B
(Wormhole: Ethereum Core Bridge)
0xd4930664...3D8cffE01
0.009515396157492247 Eth
Nonce: 764
0.009383236839227743 Eth
Nonce: 765
0.000132159318264504
0xE7ae30C0...151747911

Execution Trace

ETH 0.000024858336 NttManagerWithExecutor.transfer( nttManager=0x64E4b81023621CB08f5aC305c2dD6eDaaD717834, amount=200000000000, recipientChain=30, recipientAddress=000000000000000000000000D493066498ACE409059FDA4C1BCD2E73D8CFFE01, refundAddress=000000000000000000000000D493066498ACE409059FDA4C1BCD2E73D8CFFE01, encodedInstructions=0x01000101, executorArgs=[{name:value, type:uint256, order:1, indexed:false, value:24858336000000, valueString:24858336000000}, {name:refundAddress, type:address, order:2, indexed:false, value:0xd493066498aCe409059fDA4c1bCD2E73D8cffE01, valueString:0xd493066498aCe409059fDA4c1bCD2E73D8cffE01}, {name:signedQuote, type:bytes, order:3, indexed:false, value:0x45513031A54008017941ECE968623A0DD8EE907E2B1335960000000000000000000000006A8BFC410A3CC7306D52872F116AFB12F1CEC6C60002001E00000000689AFCA600000000000389B700000000003306C800002739B4CDB80000002739B4CDB800BB9F0EDBB011387C1F0C9EC019461839C651191AE129B95262A22C30B16F258172E75B1A9A34B71AB376E14267816338E67B64C01B5068BCB539D3CB4A527F6B1C, valueString:0x45513031A54008017941ECE968623A0DD8EE907E2B1335960000000000000000000000006A8BFC410A3CC7306D52872F116AFB12F1CEC6C60002001E00000000689AFCA600000000000389B700000000003306C800002739B4CDB80000002739B4CDB800BB9F0EDBB011387C1F0C9EC019461839C651191AE129B95262A22C30B16F258172E75B1A9A34B71AB376E14267816338E67B64C01B5068BCB539D3CB4A527F6B1C}, {name:instructions, type:bytes, order:4, indexed:false, value:0x010000000000000000000000000007A12000000000000000000000000000000000, valueString:0x010000000000000000000000000007A12000000000000000000000000000000000}], feeArgs=[{name:dbps, type:uint16, order:1, indexed:false, value:50, valueString:50}, {name:payee, type:address, order:2, indexed:false, value:0x9b2A3B92b1D86938D3Ed37B0519952C227bA6D09, valueString:0x9b2A3B92b1D86938D3Ed37B0519952C227bA6D09}] ) => ( msgId=0 )
  • 0x64e4b81023621cb08f5ac305c2dd6edaad717834.STATICCALL( )
    • 0xad3d2d108532d663123e9184f1dd87f46e488a55.DELEGATECALL( )
    • Cygnus: clBTC Token.70a08231( )
    • Cygnus: clBTC Token.23b872dd( )
    • Cygnus: clBTC Token.70a08231( )
    • 0x64e4b81023621cb08f5ac305c2dd6edaad717834.c128d170( )
      • 0xad3d2d108532d663123e9184f1dd87f46e488a55.c128d170( )
      • 0x64e4b81023621cb08f5ac305c2dd6edaad717834.STATICCALL( )
        • 0xad3d2d108532d663123e9184f1dd87f46e488a55.DELEGATECALL( )
          • Cygnus: clBTC Token.STATICCALL( )
          • Cygnus: clBTC Token.dd62ed3e( )
          • Cygnus: clBTC Token.095ea7b3( )
          • 0x64e4b81023621cb08f5ac305c2dd6edaad717834.b293f97f( )
            • 0xad3d2d108532d663123e9184f1dd87f46e488a55.b293f97f( )
              • Cygnus: clBTC Token.70a08231( )
              • Cygnus: clBTC Token.23b872dd( )
              • Cygnus: clBTC Token.70a08231( )
              • Cygnus: clBTC Token.42966c68( )
              • Cygnus: clBTC Token.70a08231( )
              • Cygnus: clBTC Token.STATICCALL( )
              • Cygnus: clBTC Token.STATICCALL( )
              • 0x8f0dea1fb3ffce6930268861fcc11efd60aea581.b620e872( )
              • 0x454f5cf9143cda1291eb80dcbbcdfab4544e0920.b5634c73( )
                • 0x0092aa9918bf93ebdbea816645816c1faee7f321.b5634c73( )
                  • Wormhole.STATICCALL( )
                    • 0x3c3d457f1522d3540ab3325aa5f1864e34cba9d0.DELEGATECALL( )
                    • 0x8f0dea1fb3ffce6930268861fcc11efd60aea581.2b9f4796( )
                    • 0x8f0dea1fb3ffce6930268861fcc11efd60aea581.8b4979b8( )
                    • 0x454f5cf9143cda1291eb80dcbbcdfab4544e0920.4b5b0505( )
                      • 0x0092aa9918bf93ebdbea816645816c1faee7f321.4b5b0505( )
                        • 0x8f0dea1fb3ffce6930268861fcc11efd60aea581.1185b23c( )
                        • Wormhole.b19a437e( )
                          • 0x3c3d457f1522d3540ab3325aa5f1864e34cba9d0.b19a437e( )
                          • Cygnus: clBTC Token.STATICCALL( )
                          • 0x64e4b81023621cb08f5ac305c2dd6edaad717834.c128d170( )
                            • 0xad3d2d108532d663123e9184f1dd87f46e488a55.c128d170( )
                            • ETH 0.000024858336 Executor.requestExecution( dstChain=30, dstAddr=000000000000000000000000429410525068B694160D686EACF72CE12B665991, refundAddr=0xd493066498aCe409059fDA4c1bCD2E73D8cffE01, signedQuoteBytes=0x45513031A54008017941ECE968623A0DD8EE907E2B1335960000000000000000000000006A8BFC410A3CC7306D52872F116AFB12F1CEC6C60002001E00000000689AFCA600000000000389B700000000003306C800002739B4CDB80000002739B4CDB800BB9F0EDBB011387C1F0C9EC019461839C651191AE129B95262A22C30B16F258172E75B1A9A34B71AB376E14267816338E67B64C01B5068BCB539D3CB4A527F6B1C, requestBytes=0x45524E31000200000000000000000000000064E4B81023621CB08F5AC305C2DD6EDAAD7178340000000000000000000000000000000000000000000000000000000000000000, relayInstructions=0x010000000000000000000000000007A12000000000000000000000000000000000 )
                              • ETH 0.000024858336 0x6a8bfc410a3cc7306d52872f116afb12f1cec6c6.CALL( )
                                File 1 of 3: NttManagerWithExecutor
                                // 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/interfaces/INttManager.sol";
                                import "./interfaces/INttManagerWithExecutor.sol";
                                string constant nttManagerWithExecutorVersion = "NttManagerWithExecutor-0.0.1";
                                /// @title NttManagerWithExecutor
                                /// @author Wormhole Project Contributors.
                                /// @notice The NttManagerWithExecutor contract is a shim contract that initiates
                                ///         an NTT transfer using the executor for relaying.
                                contract NttManagerWithExecutor is INttManagerWithExecutor {
                                    using TrimmedAmountLib for uint256;
                                    using TrimmedAmountLib for TrimmedAmount;
                                    uint16 public immutable chainId;
                                    IExecutor public immutable executor;
                                    string public constant VERSION = nttManagerWithExecutorVersion;
                                    constructor(uint16 _chainId, address _executor) {
                                        assert(_chainId != 0);
                                        assert(_executor != address(0));
                                        chainId = _chainId;
                                        executor = IExecutor(_executor);
                                    }
                                    // ==================== External Interface ===============================================
                                    /// @inheritdoc INttManagerWithExecutor
                                    function transfer(
                                        address nttManager,
                                        uint256 amount,
                                        uint16 recipientChain,
                                        bytes32 recipientAddress,
                                        bytes32 refundAddress,
                                        bytes memory encodedInstructions,
                                        ExecutorArgs calldata executorArgs,
                                        FeeArgs calldata feeArgs
                                    ) external payable returns (uint64 msgId) {
                                        INttManager nttm = INttManager(nttManager);
                                        // Custody the tokens in this contract and approve NTT to spend them.
                                        // Not worrying about dust here since the `NttManager` will revert in that case.
                                        address token = nttm.token();
                                        amount = custodyTokens(token, amount);
                                        // Transfer the fee to the referrer.
                                        amount = payFee(token, amount, feeArgs, nttm, recipientChain);
                                        // Initiate the transfer.
                                        SafeERC20.safeApprove(IERC20(token), nttManager, amount);
                                        msgId = nttm.transfer{value: msg.value - executorArgs.value}(
                                            amount, recipientChain, recipientAddress, refundAddress, false, encodedInstructions
                                        );
                                        // Generate the executor event.
                                        executor.requestExecution{value: executorArgs.value}(
                                            recipientChain,
                                            nttm.getPeer(recipientChain).peerAddress,
                                            executorArgs.refundAddress,
                                            executorArgs.signedQuote,
                                            ExecutorMessages.makeNTTv1Request(
                                                chainId, bytes32(uint256(uint160(address(nttm)))), bytes32(uint256(msgId))
                                            ),
                                            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,
                                        uint256 amount,
                                        FeeArgs calldata feeArgs,
                                        INttManager nttManager,
                                        uint16 recipientChain
                                    ) internal returns (uint256) {
                                        uint256 fee = calculateFee(amount, feeArgs.dbps);
                                        fee = trimFee(nttManager, fee, recipientChain);
                                        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 trimFee(INttManager nttManager, uint256 amount, uint16 toChain) internal view returns (uint256 newFee) {
                                        uint8 toDecimals = nttManager.getPeer(toChain).tokenDecimals;
                                        if (toDecimals == 0) {
                                            revert InvalidPeerDecimals();
                                        }
                                        uint8 fromDecimals = nttManager.tokenDecimals();
                                        TrimmedAmount trimmedAmount = amount.trim(fromDecimals, toDecimals);
                                        newFee = trimmedAmount.untrim(fromDecimals);
                                    }
                                }
                                // 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";
                                    /// @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);
                                    }
                                }
                                // SPDX-License-Identifier: Apache 2
                                pragma solidity >=0.8.8 <0.9.0;
                                import "../libraries/TrimmedAmount.sol";
                                import "../libraries/TransceiverStructs.sol";
                                import "./IManagerBase.sol";
                                interface INttManager is IManagerBase {
                                    /// @dev The peer on another chain.
                                    struct NttManagerPeer {
                                        bytes32 peerAddress;
                                        uint8 tokenDecimals;
                                    }
                                    /// @notice Emitted when a message is sent from the nttManager.
                                    /// @dev Topic0
                                    ///      0xe54e51e42099622516fa3b48e9733581c9dbdcb771cafb093f745a0532a35982.
                                    /// @param recipient The recipient of the message.
                                    /// @param refundAddress The address on the destination chain to which the
                                    ///                      refund of unused gas will be paid
                                    /// @param amount The amount transferred.
                                    /// @param fee The amount of ether sent along with the tx to cover the delivery fee.
                                    /// @param recipientChain The chain ID of the recipient.
                                    /// @param msgSequence The unique sequence ID of the message.
                                    event TransferSent(
                                        bytes32 indexed recipient,
                                        bytes32 indexed refundAddress,
                                        uint256 amount,
                                        uint256 fee,
                                        uint16 recipientChain,
                                        uint64 msgSequence
                                    );
                                    /// @notice Emitted when a message is sent from the nttManager.
                                    /// @dev Topic0
                                    ///      0x3e6ae56314c6da8b461d872f41c6d0bb69317b9d0232805aaccfa45df1a16fa0.
                                    /// @param digest The digest of the message.
                                    event TransferSent(bytes32 indexed digest);
                                    /// @notice Emitted when the peer contract is updated.
                                    /// @dev Topic0
                                    ///      0x1456404e7f41f35c3daac941bb50bad417a66275c3040061b4287d787719599d.
                                    /// @param chainId_ The chain ID of the peer contract.
                                    /// @param oldPeerContract The old peer contract address.
                                    /// @param oldPeerDecimals The old peer contract decimals.
                                    /// @param peerContract The new peer contract address.
                                    /// @param peerDecimals The new peer contract decimals.
                                    event PeerUpdated(
                                        uint16 indexed chainId_,
                                        bytes32 oldPeerContract,
                                        uint8 oldPeerDecimals,
                                        bytes32 peerContract,
                                        uint8 peerDecimals
                                    );
                                    /// @notice Emitted when a transfer has been redeemed
                                    ///         (either minted or unlocked on the recipient chain).
                                    /// @dev Topic0
                                    ///      0x504e6efe18ab9eed10dc6501a417f5b12a2f7f2b1593aed9b89f9bce3cf29a91.
                                    /// @param digest The digest of the message.
                                    event TransferRedeemed(bytes32 indexed digest);
                                    /// @notice Emitted when an outbound transfer has been cancelled
                                    /// @dev Topic0
                                    ///      0xf80e572ae1b63e2449629b6c7d783add85c36473926f216077f17ee002bcfd07.
                                    /// @param sequence The sequence number being cancelled
                                    /// @param recipient The canceller and recipient of the funds
                                    /// @param amount The amount of the transfer being cancelled
                                    event OutboundTransferCancelled(uint256 sequence, address recipient, uint256 amount);
                                    /// @notice The transfer has some dust.
                                    /// @dev Selector 0x71f0634a
                                    /// @dev This is a security measure to prevent users from losing funds.
                                    ///      This is the result of trimming the amount and then untrimming it.
                                    /// @param  amount The amount to transfer.
                                    error TransferAmountHasDust(uint256 amount, uint256 dust);
                                    /// @notice The mode is invalid. It is neither in LOCKING or BURNING mode.
                                    /// @dev Selector 0x66001a89
                                    /// @param mode The mode.
                                    error InvalidMode(uint8 mode);
                                    /// @notice Error when trying to execute a message on an unintended target chain.
                                    /// @dev Selector 0x3dcb204a.
                                    /// @param targetChain The target chain.
                                    /// @param thisChain The current chain.
                                    error InvalidTargetChain(uint16 targetChain, uint16 thisChain);
                                    /// @notice Error when the transfer amount is zero.
                                    /// @dev Selector 0x9993626a.
                                    error ZeroAmount();
                                    /// @notice Error when the recipient is invalid.
                                    /// @dev Selector 0x9c8d2cd2.
                                    error InvalidRecipient();
                                    /// @notice Error when the recipient is invalid.
                                    /// @dev Selector 0xe2fe2726.
                                    error InvalidRefundAddress();
                                    /// @notice Error when the amount burned is different than the balance difference,
                                    ///         since NTT does not support burn fees.
                                    /// @dev Selector 0x02156a8f.
                                    /// @param burnAmount The amount burned.
                                    /// @param balanceDiff The balance after burning.
                                    error BurnAmountDifferentThanBalanceDiff(uint256 burnAmount, uint256 balanceDiff);
                                    /// @notice The caller is not the deployer.
                                    error UnexpectedDeployer(address expectedOwner, address owner);
                                    /// @notice Peer for the chain does not match the configuration.
                                    /// @param chainId ChainId of the source chain.
                                    /// @param peerAddress Address of the peer nttManager contract.
                                    error InvalidPeer(uint16 chainId, bytes32 peerAddress);
                                    /// @notice Peer chain ID cannot be zero.
                                    error InvalidPeerChainIdZero();
                                    /// @notice Peer cannot be the zero address.
                                    error InvalidPeerZeroAddress();
                                    /// @notice Peer cannot have zero decimals.
                                    error InvalidPeerDecimals();
                                    /// @notice Staticcall reverted
                                    /// @dev Selector 0x1222cd83
                                    error StaticcallFailed();
                                    /// @notice Error when someone other than the original sender tries to cancel a queued outbound transfer.
                                    /// @dev Selector 0xceb40a85.
                                    /// @param canceller The address trying to cancel the transfer.
                                    /// @param sender The original sender that initiated the transfer that was queued.
                                    error CancellerNotSender(address canceller, address sender);
                                    /// @notice An unexpected msg.value was passed with the call
                                    /// @dev Selector 0xbd28e889.
                                    error UnexpectedMsgValue();
                                    /// @notice Peer cannot be on the same chain
                                    /// @dev Selector 0x20371f2a.
                                    error InvalidPeerSameChainId();
                                    /// @notice Feature is not implemented.
                                    error NotImplemented();
                                    /// @notice Transfer a given amount to a recipient on a given chain. This function is called
                                    ///         by the user to send the token cross-chain. This function will either lock or burn the
                                    ///         sender's tokens. Finally, this function will call into registered `Endpoint` contracts
                                    ///         to send a message with the incrementing sequence number and the token transfer payload.
                                    /// @param amount The amount to transfer.
                                    /// @param recipientChain The Wormhole chain ID for the destination.
                                    /// @param recipient The recipient address.
                                    /// @return msgId The resulting message ID of the transfer
                                    function transfer(
                                        uint256 amount,
                                        uint16 recipientChain,
                                        bytes32 recipient
                                    ) external payable returns (uint64 msgId);
                                    /// @notice Transfer a given amount to a recipient on a given chain. This function is called
                                    ///         by the user to send the token cross-chain. This function will either lock or burn the
                                    ///         sender's tokens. Finally, this function will call into registered `Endpoint` contracts
                                    ///         to send a message with the incrementing sequence number and the token transfer payload.
                                    /// @dev Transfers are queued if the outbound limit is hit and must be completed by the client.
                                    /// @param amount The amount to transfer.
                                    /// @param recipientChain The Wormhole chain ID for the destination.
                                    /// @param recipient The recipient address.
                                    /// @param refundAddress The address to which a refund for unussed gas is issued on the recipient chain.
                                    /// @param shouldQueue Whether the transfer should be queued if the outbound limit is hit.
                                    /// @param encodedInstructions Additional instructions to be forwarded to the recipient chain.
                                    /// @return msgId The resulting message ID of the transfer
                                    function transfer(
                                        uint256 amount,
                                        uint16 recipientChain,
                                        bytes32 recipient,
                                        bytes32 refundAddress,
                                        bool shouldQueue,
                                        bytes memory encodedInstructions
                                    ) external payable returns (uint64 msgId);
                                    /// @notice Complete an outbound transfer that's been queued.
                                    /// @dev This method is called by the client to complete an outbound transfer that's been queued.
                                    /// @param queueSequence The sequence of the message in the queue.
                                    /// @return msgSequence The sequence of the message.
                                    function completeOutboundQueuedTransfer(
                                        uint64 queueSequence
                                    ) external payable returns (uint64 msgSequence);
                                    /// @notice Cancels an outbound transfer that's been queued.
                                    /// @dev This method is called by the client to cancel an outbound transfer that's been queued.
                                    /// @param queueSequence The sequence of the message in the queue.
                                    function cancelOutboundQueuedTransfer(
                                        uint64 queueSequence
                                    ) external;
                                    /// @notice Complete an inbound queued transfer.
                                    /// @param digest The digest of the message to complete.
                                    function completeInboundQueuedTransfer(
                                        bytes32 digest
                                    ) external;
                                    /// @notice Called by an Endpoint contract to deliver a verified attestation.
                                    /// @dev This function enforces attestation threshold and replay logic for messages. Once all
                                    ///      validations are complete, this function calls `executeMsg` to execute the command specified
                                    ///      by the message.
                                    /// @param sourceChainId The Wormhole chain id of the sender.
                                    /// @param sourceNttManagerAddress The address of the sender's NTT Manager contract.
                                    /// @param payload The VAA payload.
                                    function attestationReceived(
                                        uint16 sourceChainId,
                                        bytes32 sourceNttManagerAddress,
                                        TransceiverStructs.NttManagerMessage memory payload
                                    ) external;
                                    /// @notice Called after a message has been sufficiently verified to execute
                                    ///         the command in the message. This function will decode the payload
                                    ///         as an NttManagerMessage to extract the sequence, msgType, and other parameters.
                                    /// @dev This function is exposed as a fallback for when an `Transceiver` is deregistered
                                    ///      when a message is in flight.
                                    /// @param sourceChainId The Wormhole chain id of the sender.
                                    /// @param sourceNttManagerAddress The address of the sender's nttManager contract.
                                    /// @param message The message to execute.
                                    function executeMsg(
                                        uint16 sourceChainId,
                                        bytes32 sourceNttManagerAddress,
                                        TransceiverStructs.NttManagerMessage memory message
                                    ) external;
                                    /// @notice Returns the number of decimals of the token managed by the NttManager.
                                    /// @return decimals The number of decimals of the token.
                                    function tokenDecimals() external view returns (uint8);
                                    /// @notice Returns registered peer contract for a given chain.
                                    /// @param chainId_ Wormhole chain ID.
                                    function getPeer(
                                        uint16 chainId_
                                    ) external view returns (NttManagerPeer memory);
                                    /// @notice Sets the corresponding peer.
                                    /// @dev The nttManager that executes the message sets the source nttManager as the peer.
                                    /// @param peerChainId The Wormhole chain ID of the peer.
                                    /// @param peerContract The address of the peer nttManager contract.
                                    /// @param decimals The number of decimals of the token on the peer chain.
                                    /// @param inboundLimit The inbound rate limit for the peer chain id. This is formatted in the normal
                                    ///                     token representation. e.g. a limit of 100 for a token with 6 decimals = 100_000_000
                                    function setPeer(
                                        uint16 peerChainId,
                                        bytes32 peerContract,
                                        uint8 decimals,
                                        uint256 inboundLimit
                                    ) external;
                                    /// @notice Sets the outbound transfer limit for a given chain.
                                    /// @dev This method can only be executed by the `owner`.
                                    /// @param limit The new outbound limit. This is formatted in the normal
                                    ///              token representation. e.g. a limit of 100 for a token with 6 decimals = 100_000_000
                                    function setOutboundLimit(
                                        uint256 limit
                                    ) external;
                                    /// @notice Sets the inbound transfer limit for a given chain.
                                    /// @dev This method can only be executed by the `owner`.
                                    /// @param limit The new limit. This is formatted in the normal
                                    ///              token representation. e.g. a limit of 100 for a token with 6 decimals = 100_000_000
                                    /// @param chainId The Wormhole chain ID to set the limit for.
                                    function setInboundLimit(uint256 limit, uint16 chainId) external;
                                }
                                // 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 INttManagerWithExecutor {
                                    /// @notice Error when the refund to the sender fails.
                                    /// @dev Selector 0x2ca23714.
                                    /// @param refundAmount The refund amount.
                                    error RefundFailed(uint256 refundAmount);
                                    /// @notice Peer cannot have zero decimals.
                                    error InvalidPeerDecimals();
                                    /// @notice Transfer a given amount to a recipient on a given chain using the Executor for relaying.
                                    /// @param nttManager The NTT manager used for the transfer.
                                    /// @param amount The amount to transfer.
                                    /// @param recipientChain The Wormhole chain ID for the destination.
                                    /// @param recipientAddress The recipient address.
                                    /// @param refundAddress The address to which a refund for unussed gas is issued on the recipient chain.
                                    /// @param encodedInstructions Additional instructions to be forwarded to the recipient chain.
                                    /// @param executorArgs The arguments to be passed into the Executor.
                                    /// @param feeArgs The arguments used to compute and pay the referrer fee.
                                    /// @return msgId The resulting message ID of the transfer
                                    function transfer(
                                        address nttManager,
                                        uint256 amount,
                                        uint16 recipientChain,
                                        bytes32 recipientAddress,
                                        bytes32 refundAddress,
                                        bytes memory encodedInstructions,
                                        ExecutorArgs calldata executorArgs,
                                        FeeArgs calldata feeArgs
                                    ) external payable returns (uint64 msgId);
                                }
                                // 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);
                                        }
                                    }
                                }
                                // 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.8 <0.9.0;
                                import "wormhole-solidity-sdk/libraries/BytesParsing.sol";
                                import "./TrimmedAmount.sol";
                                library TransceiverStructs {
                                    using BytesParsing for bytes;
                                    using TrimmedAmountLib for TrimmedAmount;
                                    /// @notice Error thrown when the payload length exceeds the allowed maximum.
                                    /// @dev Selector 0xa3419691.
                                    /// @param size The size of the payload.
                                    error PayloadTooLong(uint256 size);
                                    /// @notice Error thrown when the prefix of an encoded message
                                    ///         does not match the expected value.
                                    /// @dev Selector 0x56d2569d.
                                    /// @param prefix The prefix that was found in the encoded message.
                                    error IncorrectPrefix(bytes4 prefix);
                                    /// @notice Error thrown when the transceiver instructions aren't
                                    ///         encoded with strictly increasing indices
                                    /// @dev Selector 0x0555a4b9.
                                    /// @param lastIndex Last parsed instruction index
                                    /// @param instructionIndex The instruction index that was unordered
                                    error UnorderedInstructions(uint256 lastIndex, uint256 instructionIndex);
                                    /// @notice Error thrown when a transceiver instruction index
                                    ///         is greater than the number of registered transceivers
                                    /// @dev We index from 0 so if providedIndex == numTransceivers then we're out-of-bounds too
                                    /// @dev Selector 0x689f5016.
                                    /// @param providedIndex The index specified in the instruction
                                    /// @param numTransceivers The number of registered transceivers
                                    error InvalidInstructionIndex(uint256 providedIndex, uint256 numTransceivers);
                                    /// @dev Prefix for all NativeTokenTransfer payloads
                                    ///      This is 0x99'N''T''T'
                                    bytes4 constant NTT_PREFIX = 0x994E5454;
                                    /// @dev Message emitted and received by the nttManager contract.
                                    ///      The wire format is as follows:
                                    ///      - id - 32 bytes
                                    ///      - sender - 32 bytes
                                    ///      - payloadLength - 2 bytes
                                    ///      - payload - `payloadLength` bytes
                                    struct NttManagerMessage {
                                        /// @notice unique message identifier
                                        /// @dev This is incrementally assigned on EVM chains, but this is not
                                        /// guaranteed on other runtimes.
                                        bytes32 id;
                                        /// @notice original message sender address.
                                        bytes32 sender;
                                        /// @notice payload that corresponds to the type.
                                        bytes payload;
                                    }
                                    function nttManagerMessageDigest(
                                        uint16 sourceChainId,
                                        NttManagerMessage memory m
                                    ) public pure returns (bytes32) {
                                        return _nttManagerMessageDigest(sourceChainId, encodeNttManagerMessage(m));
                                    }
                                    function _nttManagerMessageDigest(
                                        uint16 sourceChainId,
                                        bytes memory encodedNttManagerMessage
                                    ) internal pure returns (bytes32) {
                                        return keccak256(abi.encodePacked(sourceChainId, encodedNttManagerMessage));
                                    }
                                    function encodeNttManagerMessage(
                                        NttManagerMessage memory m
                                    ) public pure returns (bytes memory encoded) {
                                        if (m.payload.length > type(uint16).max) {
                                            revert PayloadTooLong(m.payload.length);
                                        }
                                        uint16 payloadLength = uint16(m.payload.length);
                                        return abi.encodePacked(m.id, m.sender, payloadLength, m.payload);
                                    }
                                    /// @notice Parse a NttManagerMessage.
                                    /// @param encoded The byte array corresponding to the encoded message
                                    /// @return nttManagerMessage The parsed NttManagerMessage struct.
                                    function parseNttManagerMessage(
                                        bytes memory encoded
                                    ) public pure returns (NttManagerMessage memory nttManagerMessage) {
                                        uint256 offset = 0;
                                        (nttManagerMessage.id, offset) = encoded.asBytes32Unchecked(offset);
                                        (nttManagerMessage.sender, offset) = encoded.asBytes32Unchecked(offset);
                                        uint256 payloadLength;
                                        (payloadLength, offset) = encoded.asUint16Unchecked(offset);
                                        (nttManagerMessage.payload, offset) = encoded.sliceUnchecked(offset, payloadLength);
                                        encoded.checkLength(offset);
                                    }
                                    /// @dev Native Token Transfer payload.
                                    ///      The wire format is as follows:
                                    ///      - NTT_PREFIX - 4 bytes
                                    ///      - numDecimals - 1 byte
                                    ///      - amount - 8 bytes
                                    ///      - sourceToken - 32 bytes
                                    ///      - to - 32 bytes
                                    ///      - toChain - 2 bytes
                                    ///      - additionalPayloadLength - 2 bytes, optional
                                    ///      - additionalPayload - `additionalPayloadLength` bytes
                                    struct NativeTokenTransfer {
                                        /// @notice Amount being transferred (big-endian u64 and u8 for decimals)
                                        TrimmedAmount amount;
                                        /// @notice Source chain token address.
                                        bytes32 sourceToken;
                                        /// @notice Address of the recipient.
                                        bytes32 to;
                                        /// @notice Chain ID of the recipient
                                        uint16 toChain;
                                        /// @notice Custom payload
                                        /// @dev Recommended that the first 4 bytes are a unique prefix
                                        bytes additionalPayload;
                                    }
                                    function encodeNativeTokenTransfer(
                                        NativeTokenTransfer memory m
                                    ) public pure returns (bytes memory encoded) {
                                        // The `amount` and `decimals` fields are encoded in reverse order compared to how they are declared in the
                                        // `TrimmedAmount` type. This is consistent with the Rust NTT implementation.
                                        TrimmedAmount transferAmount = m.amount;
                                        if (m.additionalPayload.length > 0) {
                                            if (m.additionalPayload.length > type(uint16).max) {
                                                revert PayloadTooLong(m.additionalPayload.length);
                                            }
                                            uint16 additionalPayloadLength = uint16(m.additionalPayload.length);
                                            return abi.encodePacked(
                                                NTT_PREFIX,
                                                transferAmount.getDecimals(),
                                                transferAmount.getAmount(),
                                                m.sourceToken,
                                                m.to,
                                                m.toChain,
                                                additionalPayloadLength,
                                                m.additionalPayload
                                            );
                                        }
                                        return abi.encodePacked(
                                            NTT_PREFIX,
                                            transferAmount.getDecimals(),
                                            transferAmount.getAmount(),
                                            m.sourceToken,
                                            m.to,
                                            m.toChain
                                        );
                                    }
                                    /// @dev Parse a NativeTokenTransfer.
                                    /// @param encoded The byte array corresponding to the encoded message
                                    /// @return nativeTokenTransfer The parsed NativeTokenTransfer struct.
                                    function parseNativeTokenTransfer(
                                        bytes memory encoded
                                    ) public pure returns (NativeTokenTransfer memory nativeTokenTransfer) {
                                        uint256 offset = 0;
                                        bytes4 prefix;
                                        (prefix, offset) = encoded.asBytes4Unchecked(offset);
                                        if (prefix != NTT_PREFIX) {
                                            revert IncorrectPrefix(prefix);
                                        }
                                        // The `amount` and `decimals` fields are parsed in reverse order compared to how they are declared in the
                                        // `TrimmedAmount` struct. This is consistent with the Rust NTT implementation.
                                        uint8 numDecimals;
                                        (numDecimals, offset) = encoded.asUint8Unchecked(offset);
                                        uint64 amount;
                                        (amount, offset) = encoded.asUint64Unchecked(offset);
                                        nativeTokenTransfer.amount = packTrimmedAmount(amount, numDecimals);
                                        (nativeTokenTransfer.sourceToken, offset) = encoded.asBytes32Unchecked(offset);
                                        (nativeTokenTransfer.to, offset) = encoded.asBytes32Unchecked(offset);
                                        (nativeTokenTransfer.toChain, offset) = encoded.asUint16Unchecked(offset);
                                        // The additional payload may be omitted, but if it is included, it is prefixed by a u16 for its length.
                                        // If there are at least 2 bytes remaining, attempt to parse the additional payload.
                                        if (encoded.length >= offset + 2) {
                                            uint256 payloadLength;
                                            (payloadLength, offset) = encoded.asUint16Unchecked(offset);
                                            (nativeTokenTransfer.additionalPayload, offset) =
                                                encoded.sliceUnchecked(offset, payloadLength);
                                        }
                                        encoded.checkLength(offset);
                                    }
                                    /// @dev Message emitted by Transceiver implementations.
                                    ///      Each message includes an Transceiver-specified 4-byte prefix.
                                    ///      The wire format is as follows:
                                    ///      - prefix - 4 bytes
                                    ///      - sourceNttManagerAddress - 32 bytes
                                    ///      - recipientNttManagerAddress - 32 bytes
                                    ///      - nttManagerPayloadLength - 2 bytes
                                    ///      - nttManagerPayload - `nttManagerPayloadLength` bytes
                                    ///      - transceiverPayloadLength - 2 bytes
                                    ///      - transceiverPayload - `transceiverPayloadLength` bytes
                                    struct TransceiverMessage {
                                        /// @notice Address of the NttManager contract that emitted this message.
                                        bytes32 sourceNttManagerAddress;
                                        /// @notice Address of the NttManager contract that receives this message.
                                        bytes32 recipientNttManagerAddress;
                                        /// @notice Payload provided to the Transceiver contract by the NttManager contract.
                                        bytes nttManagerPayload;
                                        /// @notice Optional payload that the transceiver can encode and use for its own message passing purposes.
                                        bytes transceiverPayload;
                                    }
                                    // @notice Encodes an Transceiver message for communication between the
                                    //         NttManager and the Transceiver.
                                    // @param m The TransceiverMessage struct containing the message details.
                                    // @return encoded The byte array corresponding to the encoded message.
                                    // @custom:throw PayloadTooLong if the length of transceiverId, nttManagerPayload,
                                    //         or transceiverPayload exceeds the allowed maximum.
                                    function encodeTransceiverMessage(
                                        bytes4 prefix,
                                        TransceiverMessage memory m
                                    ) public pure returns (bytes memory encoded) {
                                        if (m.nttManagerPayload.length > type(uint16).max) {
                                            revert PayloadTooLong(m.nttManagerPayload.length);
                                        }
                                        uint16 nttManagerPayloadLength = uint16(m.nttManagerPayload.length);
                                        if (m.transceiverPayload.length > type(uint16).max) {
                                            revert PayloadTooLong(m.transceiverPayload.length);
                                        }
                                        uint16 transceiverPayloadLength = uint16(m.transceiverPayload.length);
                                        return abi.encodePacked(
                                            prefix,
                                            m.sourceNttManagerAddress,
                                            m.recipientNttManagerAddress,
                                            nttManagerPayloadLength,
                                            m.nttManagerPayload,
                                            transceiverPayloadLength,
                                            m.transceiverPayload
                                        );
                                    }
                                    function buildAndEncodeTransceiverMessage(
                                        bytes4 prefix,
                                        bytes32 sourceNttManagerAddress,
                                        bytes32 recipientNttManagerAddress,
                                        bytes memory nttManagerMessage,
                                        bytes memory transceiverPayload
                                    ) public pure returns (TransceiverMessage memory, bytes memory) {
                                        TransceiverMessage memory transceiverMessage = TransceiverMessage({
                                            sourceNttManagerAddress: sourceNttManagerAddress,
                                            recipientNttManagerAddress: recipientNttManagerAddress,
                                            nttManagerPayload: nttManagerMessage,
                                            transceiverPayload: transceiverPayload
                                        });
                                        bytes memory encoded = encodeTransceiverMessage(prefix, transceiverMessage);
                                        return (transceiverMessage, encoded);
                                    }
                                    /// @dev Parses an encoded message and extracts information into an TransceiverMessage struct.
                                    /// @param encoded The encoded bytes containing information about the TransceiverMessage.
                                    /// @return transceiverMessage The parsed TransceiverMessage struct.
                                    /// @custom:throw IncorrectPrefix if the prefix of the encoded message does not
                                    ///         match the expected prefix.
                                    function parseTransceiverMessage(
                                        bytes4 expectedPrefix,
                                        bytes memory encoded
                                    ) internal pure returns (TransceiverMessage memory transceiverMessage) {
                                        uint256 offset = 0;
                                        bytes4 prefix;
                                        (prefix, offset) = encoded.asBytes4Unchecked(offset);
                                        if (prefix != expectedPrefix) {
                                            revert IncorrectPrefix(prefix);
                                        }
                                        (transceiverMessage.sourceNttManagerAddress, offset) = encoded.asBytes32Unchecked(offset);
                                        (transceiverMessage.recipientNttManagerAddress, offset) = encoded.asBytes32Unchecked(offset);
                                        uint16 nttManagerPayloadLength;
                                        (nttManagerPayloadLength, offset) = encoded.asUint16Unchecked(offset);
                                        (transceiverMessage.nttManagerPayload, offset) =
                                            encoded.sliceUnchecked(offset, nttManagerPayloadLength);
                                        uint16 transceiverPayloadLength;
                                        (transceiverPayloadLength, offset) = encoded.asUint16Unchecked(offset);
                                        (transceiverMessage.transceiverPayload, offset) =
                                            encoded.sliceUnchecked(offset, transceiverPayloadLength);
                                        // Check if the entire byte array has been processed
                                        encoded.checkLength(offset);
                                    }
                                    /// @dev Parses the payload of an Transceiver message and returns
                                    ///      the parsed NttManagerMessage struct.
                                    /// @param expectedPrefix The prefix that should be encoded in the nttManager message.
                                    /// @param payload The payload sent across the wire.
                                    function parseTransceiverAndNttManagerMessage(
                                        bytes4 expectedPrefix,
                                        bytes memory payload
                                    ) public pure returns (TransceiverMessage memory, NttManagerMessage memory) {
                                        // parse the encoded message payload from the Transceiver
                                        TransceiverMessage memory parsedTransceiverMessage =
                                            parseTransceiverMessage(expectedPrefix, payload);
                                        // parse the encoded message payload from the NttManager
                                        NttManagerMessage memory parsedNttManagerMessage =
                                            parseNttManagerMessage(parsedTransceiverMessage.nttManagerPayload);
                                        return (parsedTransceiverMessage, parsedNttManagerMessage);
                                    }
                                    /// @dev Variable-length transceiver-specific instruction that can be passed by the caller to the nttManager.
                                    ///      The index field refers to the index of the registeredTransceiver that this instruction should be passed to.
                                    ///      The serialization format is:
                                    ///      - index - 1 byte
                                    ///      - payloadLength - 1 byte
                                    ///      - payload - `payloadLength` bytes
                                    struct TransceiverInstruction {
                                        uint8 index;
                                        bytes payload;
                                    }
                                    function encodeTransceiverInstruction(
                                        TransceiverInstruction memory instruction
                                    ) public pure returns (bytes memory) {
                                        if (instruction.payload.length > type(uint8).max) {
                                            revert PayloadTooLong(instruction.payload.length);
                                        }
                                        uint8 payloadLength = uint8(instruction.payload.length);
                                        return abi.encodePacked(instruction.index, payloadLength, instruction.payload);
                                    }
                                    function parseTransceiverInstructionUnchecked(
                                        bytes memory encoded,
                                        uint256 offset
                                    ) public pure returns (TransceiverInstruction memory instruction, uint256 nextOffset) {
                                        (instruction.index, nextOffset) = encoded.asUint8Unchecked(offset);
                                        uint8 instructionLength;
                                        (instructionLength, nextOffset) = encoded.asUint8Unchecked(nextOffset);
                                        (instruction.payload, nextOffset) = encoded.sliceUnchecked(nextOffset, instructionLength);
                                    }
                                    function parseTransceiverInstructionChecked(
                                        bytes memory encoded
                                    ) public pure returns (TransceiverInstruction memory instruction) {
                                        uint256 offset = 0;
                                        (instruction, offset) = parseTransceiverInstructionUnchecked(encoded, offset);
                                        encoded.checkLength(offset);
                                    }
                                    /// @dev Encode an array of multiple variable-length transceiver-specific instructions.
                                    ///      The serialization format is:
                                    ///      - instructionsLength - 1 byte
                                    ///      - `instructionsLength` number of serialized `TransceiverInstruction` types.
                                    function encodeTransceiverInstructions(
                                        TransceiverInstruction[] memory instructions
                                    ) public pure returns (bytes memory) {
                                        if (instructions.length > type(uint8).max) {
                                            revert PayloadTooLong(instructions.length);
                                        }
                                        uint256 instructionsLength = instructions.length;
                                        bytes memory encoded;
                                        for (uint256 i = 0; i < instructionsLength; i++) {
                                            bytes memory innerEncoded = encodeTransceiverInstruction(instructions[i]);
                                            encoded = bytes.concat(encoded, innerEncoded);
                                        }
                                        return abi.encodePacked(uint8(instructionsLength), encoded);
                                    }
                                    function parseTransceiverInstructions(
                                        bytes memory encoded,
                                        uint256 numRegisteredTransceivers
                                    ) public pure returns (TransceiverInstruction[] memory) {
                                        uint256 offset = 0;
                                        uint256 instructionsLength;
                                        (instructionsLength, offset) = encoded.asUint8Unchecked(offset);
                                        // We allocate an array with the length of the number of registered transceivers
                                        // This gives us the flexibility to not have to pass instructions for transceivers that
                                        // don't need them
                                        TransceiverInstruction[] memory instructions =
                                            new TransceiverInstruction[](numRegisteredTransceivers);
                                        uint256 lastIndex = 0;
                                        for (uint256 i = 0; i < instructionsLength; i++) {
                                            TransceiverInstruction memory instruction;
                                            (instruction, offset) = parseTransceiverInstructionUnchecked(encoded, offset);
                                            uint8 instructionIndex = instruction.index;
                                            // The instructions passed in have to be strictly increasing in terms of transceiver index
                                            if (i != 0 && instructionIndex <= lastIndex) {
                                                revert UnorderedInstructions(lastIndex, instructionIndex);
                                            }
                                            // Instruction index is out of bounds
                                            if (instructionIndex >= numRegisteredTransceivers) {
                                                revert InvalidInstructionIndex(instructionIndex, numRegisteredTransceivers);
                                            }
                                            lastIndex = instructionIndex;
                                            instructions[instructionIndex] = instruction;
                                        }
                                        encoded.checkLength(offset);
                                        return instructions;
                                    }
                                    struct TransceiverInit {
                                        bytes4 transceiverIdentifier;
                                        bytes32 nttManagerAddress;
                                        uint8 nttManagerMode;
                                        bytes32 tokenAddress;
                                        uint8 tokenDecimals;
                                    }
                                    function encodeTransceiverInit(
                                        TransceiverInit memory init
                                    ) public pure returns (bytes memory) {
                                        return abi.encodePacked(
                                            init.transceiverIdentifier,
                                            init.nttManagerAddress,
                                            init.nttManagerMode,
                                            init.tokenAddress,
                                            init.tokenDecimals
                                        );
                                    }
                                    function decodeTransceiverInit(
                                        bytes memory encoded
                                    ) public pure returns (TransceiverInit memory init) {
                                        uint256 offset = 0;
                                        (init.transceiverIdentifier, offset) = encoded.asBytes4Unchecked(offset);
                                        (init.nttManagerAddress, offset) = encoded.asBytes32Unchecked(offset);
                                        (init.nttManagerMode, offset) = encoded.asUint8Unchecked(offset);
                                        (init.tokenAddress, offset) = encoded.asBytes32Unchecked(offset);
                                        (init.tokenDecimals, offset) = encoded.asUint8Unchecked(offset);
                                        encoded.checkLength(offset);
                                    }
                                    struct TransceiverRegistration {
                                        bytes4 transceiverIdentifier;
                                        uint16 transceiverChainId;
                                        bytes32 transceiverAddress;
                                    }
                                    function encodeTransceiverRegistration(
                                        TransceiverRegistration memory registration
                                    ) public pure returns (bytes memory) {
                                        return abi.encodePacked(
                                            registration.transceiverIdentifier,
                                            registration.transceiverChainId,
                                            registration.transceiverAddress
                                        );
                                    }
                                    function decodeTransceiverRegistration(
                                        bytes memory encoded
                                    ) public pure returns (TransceiverRegistration memory registration) {
                                        uint256 offset = 0;
                                        (registration.transceiverIdentifier, offset) = encoded.asBytes4Unchecked(offset);
                                        (registration.transceiverChainId, offset) = encoded.asUint16Unchecked(offset);
                                        (registration.transceiverAddress, offset) = encoded.asBytes32Unchecked(offset);
                                        encoded.checkLength(offset);
                                    }
                                }
                                // SPDX-License-Identifier: Apache 2
                                pragma solidity >=0.8.8 <0.9.0;
                                import "../libraries/TransceiverStructs.sol";
                                interface IManagerBase {
                                    /// @notice The mode is either LOCKING or BURNING. In LOCKING mode, the NttManager locks the
                                    ///         tokens of the sender and mints an equivalent amount on the target chain. In BURNING
                                    ///         mode, the NttManager burns the tokens of the sender and mints an equivalent amount
                                    ///         on the target chain.LOCKING mode preserves the total supply of the tokens.
                                    enum Mode {
                                        LOCKING,
                                        BURNING
                                    }
                                    /// @notice Information about attestations for a given message.
                                    /// @dev The fields are as follows:
                                    ///      - executed: whether the message has been executed.
                                    ///      - attested: bitmap of transceivers that have attested to this message.
                                    ///                  (NOTE: might contain disabled transceivers)
                                    struct AttestationInfo {
                                        bool executed;
                                        uint64 attestedTransceivers;
                                    }
                                    struct _Sequence {
                                        uint64 num;
                                    }
                                    struct _Threshold {
                                        uint8 num;
                                    }
                                    /// @notice Emitted when a message has been attested to.
                                    /// @dev Topic0
                                    ///      0x35a2101eaac94b493e0dfca061f9a7f087913fde8678e7cde0aca9897edba0e5.
                                    /// @param digest The digest of the message.
                                    /// @param transceiver The address of the transceiver.
                                    /// @param index The index of the transceiver in the bitmap.
                                    event MessageAttestedTo(bytes32 digest, address transceiver, uint8 index);
                                    /// @notice Emmitted when the threshold required transceivers is changed.
                                    /// @dev Topic0
                                    ///      0x2a855b929b9a53c6fb5b5ed248b27e502b709c088e036a5aa17620c8fc5085a9.
                                    /// @param oldThreshold The old threshold.
                                    /// @param threshold The new threshold.
                                    event ThresholdChanged(uint8 oldThreshold, uint8 threshold);
                                    /// @notice Emitted when an transceiver is removed from the nttManager.
                                    /// @dev Topic0
                                    ///      0xf05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5.
                                    /// @param transceiver The address of the transceiver.
                                    /// @param transceiversNum The current number of transceivers.
                                    /// @param threshold The current threshold of transceivers.
                                    event TransceiverAdded(address transceiver, uint256 transceiversNum, uint8 threshold);
                                    /// @notice Emitted when an transceiver is removed from the nttManager.
                                    /// @dev Topic0
                                    ///     0x697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f.
                                    /// @param transceiver The address of the transceiver.
                                    /// @param threshold The current threshold of transceivers.
                                    event TransceiverRemoved(address transceiver, uint8 threshold);
                                    /// @notice payment for a transfer is too low.
                                    /// @param requiredPayment The required payment.
                                    /// @param providedPayment The provided payment.
                                    error DeliveryPaymentTooLow(uint256 requiredPayment, uint256 providedPayment);
                                    /// @notice Error when the refund to the sender fails.
                                    /// @dev Selector 0x2ca23714.
                                    /// @param refundAmount The refund amount.
                                    error RefundFailed(uint256 refundAmount);
                                    /// @notice The number of thresholds should not be zero.
                                    error ZeroThreshold();
                                    error RetrievedIncorrectRegisteredTransceivers(uint256 retrieved, uint256 registered);
                                    /// @notice The threshold for transceiver attestations is too high.
                                    /// @param threshold The threshold.
                                    /// @param transceivers The number of transceivers.
                                    error ThresholdTooHigh(uint256 threshold, uint256 transceivers);
                                    /// @notice Error when the tranceiver already attested to the message.
                                    ///         To ensure the client does not continue to initiate calls to the attestationReceived function.
                                    /// @dev Selector 0x2113894.
                                    /// @param nttManagerMessageHash The hash of the message.
                                    error TransceiverAlreadyAttestedToMessage(bytes32 nttManagerMessageHash);
                                    /// @notice Error when the message is not approved.
                                    /// @dev Selector 0x451c4fb0.
                                    /// @param msgHash The hash of the message.
                                    error MessageNotApproved(bytes32 msgHash);
                                    /// @notice Emitted when a message has already been executed to
                                    ///         notify client of against retries.
                                    /// @dev Topic0
                                    ///      0x4069dff8c9df7e38d2867c0910bd96fd61787695e5380281148c04932d02bef2.
                                    /// @param sourceNttManager The address of the source nttManager.
                                    /// @param msgHash The keccak-256 hash of the message.
                                    event MessageAlreadyExecuted(bytes32 indexed sourceNttManager, bytes32 indexed msgHash);
                                    /// @notice There are no transceivers enabled with the Manager
                                    /// @dev Selector 0x69cf632a
                                    error NoEnabledTransceivers();
                                    /// @notice Error when the manager doesn't have a peer registered for the destination chain
                                    /// @dev Selector 0x3af256bc.
                                    /// @param chainId The target Wormhole chain id
                                    error PeerNotRegistered(uint16 chainId);
                                    /// @notice Fetch the delivery price for a given recipient chain transfer.
                                    /// @param recipientChain The Wormhole chain ID of the transfer destination.
                                    /// @param transceiverInstructions The transceiver specific instructions for quoting and sending
                                    /// @return - The delivery prices associated with each enabled endpoint and the total price.
                                    function quoteDeliveryPrice(
                                        uint16 recipientChain,
                                        bytes memory transceiverInstructions
                                    ) external view returns (uint256[] memory, uint256);
                                    /// @notice Sets the threshold for the number of attestations required for a message
                                    /// to be considered valid.
                                    /// @param threshold The new threshold (number of attestations).
                                    /// @dev This method can only be executed by the `owner`.
                                    function setThreshold(
                                        uint8 threshold
                                    ) external;
                                    /// @notice Sets the transceiver for the given chain.
                                    /// @param transceiver The address of the transceiver.
                                    /// @dev This method can only be executed by the `owner`.
                                    function setTransceiver(
                                        address transceiver
                                    ) external;
                                    /// @notice Removes the transceiver for the given chain.
                                    /// @param transceiver The address of the transceiver.
                                    /// @dev This method can only be executed by the `owner`.
                                    function removeTransceiver(
                                        address transceiver
                                    ) external;
                                    /// @notice Checks if a message has been approved. The message should have at least
                                    /// the minimum threshold of attestations from distinct endpoints.
                                    /// @param digest The digest of the message.
                                    /// @return - Boolean indicating if message has been approved.
                                    function isMessageApproved(
                                        bytes32 digest
                                    ) external view returns (bool);
                                    /// @notice Checks if a message has been executed.
                                    /// @param digest The digest of the message.
                                    /// @return - Boolean indicating if message has been executed.
                                    function isMessageExecuted(
                                        bytes32 digest
                                    ) external view returns (bool);
                                    /// @notice Returns the next message sequence.
                                    function nextMessageSequence() external view returns (uint64);
                                    /// @notice Upgrades to a new manager implementation.
                                    /// @dev This is upgraded via a proxy, and can only be executed
                                    /// by the `owner`.
                                    /// @param newImplementation The address of the new implementation.
                                    function upgrade(
                                        address newImplementation
                                    ) external;
                                    /// @notice Pauses the manager.
                                    function pause() external;
                                    /// @notice Returns the mode (locking or burning) of the NttManager.
                                    /// @return mode A uint8 corresponding to the mode
                                    function getMode() external view returns (uint8);
                                    /// @notice Returns the number of Transceivers that must attest to a msgId for
                                    /// it to be considered valid and acted upon.
                                    function getThreshold() external view returns (uint8);
                                    /// @notice Returns a boolean indicating if the transceiver has attested to the message.
                                    /// @param digest The digest of the message.
                                    /// @param index The index of the transceiver
                                    /// @return - Boolean indicating whether the transceiver at index `index` attested to a message digest
                                    function transceiverAttestedToMessage(
                                        bytes32 digest,
                                        uint8 index
                                    ) external view returns (bool);
                                    /// @notice Returns the number of attestations for a given message.
                                    /// @param digest The digest of the message.
                                    /// @return count The number of attestations received for the given message digest
                                    function messageAttestations(
                                        bytes32 digest
                                    ) external view returns (uint8 count);
                                    /// @notice Returns of the address of the token managed by this contract.
                                    function token() external view returns (address);
                                    /// @notice Returns the chain ID.
                                    function chainId() external view returns (uint16);
                                }
                                // 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.13;
                                library BytesParsing {
                                  uint256 private constant freeMemoryPtr = 0x40;
                                  uint256 private constant wordSize = 32;
                                  error OutOfBounds(uint256 offset, uint256 length);
                                  error LengthMismatch(uint256 encodedLength, uint256 expectedLength);
                                  error InvalidBoolVal(uint8 val);
                                  function checkBound(uint offset, uint length) internal pure {
                                    if (offset > length)
                                      revert OutOfBounds(offset, length);
                                  }
                                  function checkLength(bytes memory encoded, uint256 expected) internal pure {
                                    if (encoded.length != expected)
                                      revert LengthMismatch(encoded.length, expected);
                                  }
                                  function sliceUnchecked(
                                    bytes memory encoded,
                                    uint offset,
                                    uint length
                                  ) internal pure returns (bytes memory ret, uint nextOffset) {
                                    //bail early for degenerate case
                                    if (length == 0)
                                      return (new bytes(0), offset);
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, length)
                                      ret := mload(freeMemoryPtr)
                                      //Explanation on how we copy data here:
                                      //  The bytes type has the following layout in memory:
                                      //    [length: 32 bytes, data: length bytes]
                                      //  So if we allocate `bytes memory foo = new bytes(1);` then `foo` will be a pointer to 33
                                      //    bytes where the first 32 bytes contain the length and the last byte is the actual data.
                                      //  Since mload always loads 32 bytes of memory at once, we use our shift variable to align
                                      //    our reads so that our last read lines up exactly with the last 32 bytes of `encoded`.
                                      //  However this also means that if the length of `encoded` is not a multiple of 32 bytes, our
                                      //    first read will necessarily partly contain bytes from `encoded`'s 32 length bytes that
                                      //    will be written into the length part of our `ret` slice.
                                      //  We remedy this issue by writing the length of our `ret` slice at the end, thus
                                      //    overwritting those garbage bytes.
                                      let shift := and(length, 31) //equivalent to `mod(length, 32)` but 2 gas cheaper
                                      if iszero(shift) {
                                        shift := wordSize
                                      }
                                      let dest := add(ret, shift)
                                      let end := add(dest, length)
                                      for {
                                        let src := add(add(encoded, shift), offset)
                                      } lt(dest, end) {
                                        src := add(src, wordSize)
                                        dest := add(dest, wordSize)
                                      } {
                                        mstore(dest, mload(src))
                                      }
                                      mstore(ret, length)
                                      //When compiling with --via-ir then normally allocated memory (i.e. via new) will have 32 byte
                                      //  memory alignment and so we enforce the same memory alignment here.
                                      mstore(freeMemoryPtr, and(add(dest, 31), not(31)))
                                    }
                                  }
                                  function slice(
                                    bytes memory encoded,
                                    uint offset,
                                    uint length
                                  ) internal pure returns (bytes memory ret, uint nextOffset) {
                                    (ret, nextOffset) = sliceUnchecked(encoded, offset, length);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asAddressUnchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (address, uint) {
                                    (uint160 ret, uint nextOffset) = asUint160Unchecked(encoded, offset);
                                    return (address(ret), nextOffset);
                                  }
                                  function asAddress(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (address ret, uint nextOffset) {
                                    (ret, nextOffset) = asAddressUnchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBoolUnchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bool, uint) {
                                    (uint8 val, uint nextOffset) = asUint8Unchecked(encoded, offset);
                                    if (val & 0xfe != 0)
                                      revert InvalidBoolVal(val);
                                    uint cleanedVal = uint(val);
                                    bool ret;
                                    //skip 2x iszero opcode
                                    assembly ("memory-safe") {
                                      ret := cleanedVal
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asBool(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bool ret, uint nextOffset) {
                                    (ret, nextOffset) = asBoolUnchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                /* -------------------------------------------------------------------------------------------------
                                Remaining library code below was auto-generated by via the following js/node code:
                                for (let bytes = 1; bytes <= 32; ++bytes) {
                                  const bits = bytes*8;
                                  console.log(
                                `function asUint${bits}Unchecked(
                                  bytes memory encoded,
                                  uint offset
                                ) internal pure returns (uint${bits} ret, uint nextOffset) {
                                  assembly ("memory-safe") {
                                    nextOffset := add(offset, ${bytes})
                                    ret := mload(add(encoded, nextOffset))
                                  }
                                  return (ret, nextOffset);
                                }
                                function asUint${bits}(
                                  bytes memory encoded,
                                  uint offset
                                ) internal pure returns (uint${bits} ret, uint nextOffset) {
                                  (ret, nextOffset) = asUint${bits}Unchecked(encoded, offset);
                                  checkBound(nextOffset, encoded.length);
                                }
                                function asBytes${bytes}Unchecked(
                                  bytes memory encoded,
                                  uint offset
                                ) internal pure returns (bytes${bytes}, uint) {
                                  (uint${bits} ret, uint nextOffset) = asUint${bits}Unchecked(encoded, offset);
                                  return (bytes${bytes}(ret), nextOffset);
                                }
                                function asBytes${bytes}(
                                  bytes memory encoded,
                                  uint offset
                                ) internal pure returns (bytes${bytes}, uint) {
                                  (uint${bits} ret, uint nextOffset) = asUint${bits}(encoded, offset);
                                  return (bytes${bytes}(ret), nextOffset);
                                }
                                `
                                  );
                                }
                                ------------------------------------------------------------------------------------------------- */
                                  function asUint8Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint8 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 1)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint8(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint8 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint8Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes1Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes1, uint) {
                                    (uint8 ret, uint nextOffset) = asUint8Unchecked(encoded, offset);
                                    return (bytes1(ret), nextOffset);
                                  }
                                  function asBytes1(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes1, uint) {
                                    (uint8 ret, uint nextOffset) = asUint8(encoded, offset);
                                    return (bytes1(ret), nextOffset);
                                  }
                                  function asUint16Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint16 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 2)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint16(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint16 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint16Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes2Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes2, uint) {
                                    (uint16 ret, uint nextOffset) = asUint16Unchecked(encoded, offset);
                                    return (bytes2(ret), nextOffset);
                                  }
                                  function asBytes2(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes2, uint) {
                                    (uint16 ret, uint nextOffset) = asUint16(encoded, offset);
                                    return (bytes2(ret), nextOffset);
                                  }
                                  function asUint24Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint24 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 3)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint24(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint24 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint24Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes3Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes3, uint) {
                                    (uint24 ret, uint nextOffset) = asUint24Unchecked(encoded, offset);
                                    return (bytes3(ret), nextOffset);
                                  }
                                  function asBytes3(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes3, uint) {
                                    (uint24 ret, uint nextOffset) = asUint24(encoded, offset);
                                    return (bytes3(ret), nextOffset);
                                  }
                                  function asUint32Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint32 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 4)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint32(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint32 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint32Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes4Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes4, uint) {
                                    (uint32 ret, uint nextOffset) = asUint32Unchecked(encoded, offset);
                                    return (bytes4(ret), nextOffset);
                                  }
                                  function asBytes4(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes4, uint) {
                                    (uint32 ret, uint nextOffset) = asUint32(encoded, offset);
                                    return (bytes4(ret), nextOffset);
                                  }
                                  function asUint40Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint40 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 5)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint40(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint40 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint40Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes5Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes5, uint) {
                                    (uint40 ret, uint nextOffset) = asUint40Unchecked(encoded, offset);
                                    return (bytes5(ret), nextOffset);
                                  }
                                  function asBytes5(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes5, uint) {
                                    (uint40 ret, uint nextOffset) = asUint40(encoded, offset);
                                    return (bytes5(ret), nextOffset);
                                  }
                                  function asUint48Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint48 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 6)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint48(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint48 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint48Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes6Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes6, uint) {
                                    (uint48 ret, uint nextOffset) = asUint48Unchecked(encoded, offset);
                                    return (bytes6(ret), nextOffset);
                                  }
                                  function asBytes6(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes6, uint) {
                                    (uint48 ret, uint nextOffset) = asUint48(encoded, offset);
                                    return (bytes6(ret), nextOffset);
                                  }
                                  function asUint56Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint56 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 7)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint56(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint56 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint56Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes7Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes7, uint) {
                                    (uint56 ret, uint nextOffset) = asUint56Unchecked(encoded, offset);
                                    return (bytes7(ret), nextOffset);
                                  }
                                  function asBytes7(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes7, uint) {
                                    (uint56 ret, uint nextOffset) = asUint56(encoded, offset);
                                    return (bytes7(ret), nextOffset);
                                  }
                                  function asUint64Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint64 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 8)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint64(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint64 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint64Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes8Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes8, uint) {
                                    (uint64 ret, uint nextOffset) = asUint64Unchecked(encoded, offset);
                                    return (bytes8(ret), nextOffset);
                                  }
                                  function asBytes8(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes8, uint) {
                                    (uint64 ret, uint nextOffset) = asUint64(encoded, offset);
                                    return (bytes8(ret), nextOffset);
                                  }
                                  function asUint72Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint72 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 9)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint72(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint72 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint72Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes9Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes9, uint) {
                                    (uint72 ret, uint nextOffset) = asUint72Unchecked(encoded, offset);
                                    return (bytes9(ret), nextOffset);
                                  }
                                  function asBytes9(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes9, uint) {
                                    (uint72 ret, uint nextOffset) = asUint72(encoded, offset);
                                    return (bytes9(ret), nextOffset);
                                  }
                                  function asUint80Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint80 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 10)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint80(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint80 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint80Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes10Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes10, uint) {
                                    (uint80 ret, uint nextOffset) = asUint80Unchecked(encoded, offset);
                                    return (bytes10(ret), nextOffset);
                                  }
                                  function asBytes10(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes10, uint) {
                                    (uint80 ret, uint nextOffset) = asUint80(encoded, offset);
                                    return (bytes10(ret), nextOffset);
                                  }
                                  function asUint88Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint88 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 11)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint88(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint88 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint88Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes11Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes11, uint) {
                                    (uint88 ret, uint nextOffset) = asUint88Unchecked(encoded, offset);
                                    return (bytes11(ret), nextOffset);
                                  }
                                  function asBytes11(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes11, uint) {
                                    (uint88 ret, uint nextOffset) = asUint88(encoded, offset);
                                    return (bytes11(ret), nextOffset);
                                  }
                                  function asUint96Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint96 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 12)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint96(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint96 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint96Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes12Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes12, uint) {
                                    (uint96 ret, uint nextOffset) = asUint96Unchecked(encoded, offset);
                                    return (bytes12(ret), nextOffset);
                                  }
                                  function asBytes12(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes12, uint) {
                                    (uint96 ret, uint nextOffset) = asUint96(encoded, offset);
                                    return (bytes12(ret), nextOffset);
                                  }
                                  function asUint104Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint104 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 13)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint104(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint104 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint104Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes13Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes13, uint) {
                                    (uint104 ret, uint nextOffset) = asUint104Unchecked(encoded, offset);
                                    return (bytes13(ret), nextOffset);
                                  }
                                  function asBytes13(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes13, uint) {
                                    (uint104 ret, uint nextOffset) = asUint104(encoded, offset);
                                    return (bytes13(ret), nextOffset);
                                  }
                                  function asUint112Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint112 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 14)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint112(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint112 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint112Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes14Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes14, uint) {
                                    (uint112 ret, uint nextOffset) = asUint112Unchecked(encoded, offset);
                                    return (bytes14(ret), nextOffset);
                                  }
                                  function asBytes14(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes14, uint) {
                                    (uint112 ret, uint nextOffset) = asUint112(encoded, offset);
                                    return (bytes14(ret), nextOffset);
                                  }
                                  function asUint120Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint120 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 15)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint120(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint120 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint120Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes15Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes15, uint) {
                                    (uint120 ret, uint nextOffset) = asUint120Unchecked(encoded, offset);
                                    return (bytes15(ret), nextOffset);
                                  }
                                  function asBytes15(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes15, uint) {
                                    (uint120 ret, uint nextOffset) = asUint120(encoded, offset);
                                    return (bytes15(ret), nextOffset);
                                  }
                                  function asUint128Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint128 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 16)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint128(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint128 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint128Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes16Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes16, uint) {
                                    (uint128 ret, uint nextOffset) = asUint128Unchecked(encoded, offset);
                                    return (bytes16(ret), nextOffset);
                                  }
                                  function asBytes16(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes16, uint) {
                                    (uint128 ret, uint nextOffset) = asUint128(encoded, offset);
                                    return (bytes16(ret), nextOffset);
                                  }
                                  function asUint136Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint136 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 17)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint136(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint136 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint136Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes17Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes17, uint) {
                                    (uint136 ret, uint nextOffset) = asUint136Unchecked(encoded, offset);
                                    return (bytes17(ret), nextOffset);
                                  }
                                  function asBytes17(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes17, uint) {
                                    (uint136 ret, uint nextOffset) = asUint136(encoded, offset);
                                    return (bytes17(ret), nextOffset);
                                  }
                                  function asUint144Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint144 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 18)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint144(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint144 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint144Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes18Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes18, uint) {
                                    (uint144 ret, uint nextOffset) = asUint144Unchecked(encoded, offset);
                                    return (bytes18(ret), nextOffset);
                                  }
                                  function asBytes18(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes18, uint) {
                                    (uint144 ret, uint nextOffset) = asUint144(encoded, offset);
                                    return (bytes18(ret), nextOffset);
                                  }
                                  function asUint152Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint152 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 19)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint152(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint152 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint152Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes19Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes19, uint) {
                                    (uint152 ret, uint nextOffset) = asUint152Unchecked(encoded, offset);
                                    return (bytes19(ret), nextOffset);
                                  }
                                  function asBytes19(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes19, uint) {
                                    (uint152 ret, uint nextOffset) = asUint152(encoded, offset);
                                    return (bytes19(ret), nextOffset);
                                  }
                                  function asUint160Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint160 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 20)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint160(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint160 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint160Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes20Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes20, uint) {
                                    (uint160 ret, uint nextOffset) = asUint160Unchecked(encoded, offset);
                                    return (bytes20(ret), nextOffset);
                                  }
                                  function asBytes20(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes20, uint) {
                                    (uint160 ret, uint nextOffset) = asUint160(encoded, offset);
                                    return (bytes20(ret), nextOffset);
                                  }
                                  function asUint168Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint168 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 21)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint168(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint168 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint168Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes21Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes21, uint) {
                                    (uint168 ret, uint nextOffset) = asUint168Unchecked(encoded, offset);
                                    return (bytes21(ret), nextOffset);
                                  }
                                  function asBytes21(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes21, uint) {
                                    (uint168 ret, uint nextOffset) = asUint168(encoded, offset);
                                    return (bytes21(ret), nextOffset);
                                  }
                                  function asUint176Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint176 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 22)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint176(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint176 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint176Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes22Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes22, uint) {
                                    (uint176 ret, uint nextOffset) = asUint176Unchecked(encoded, offset);
                                    return (bytes22(ret), nextOffset);
                                  }
                                  function asBytes22(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes22, uint) {
                                    (uint176 ret, uint nextOffset) = asUint176(encoded, offset);
                                    return (bytes22(ret), nextOffset);
                                  }
                                  function asUint184Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint184 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 23)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint184(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint184 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint184Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes23Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes23, uint) {
                                    (uint184 ret, uint nextOffset) = asUint184Unchecked(encoded, offset);
                                    return (bytes23(ret), nextOffset);
                                  }
                                  function asBytes23(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes23, uint) {
                                    (uint184 ret, uint nextOffset) = asUint184(encoded, offset);
                                    return (bytes23(ret), nextOffset);
                                  }
                                  function asUint192Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint192 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 24)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint192(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint192 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint192Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes24Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes24, uint) {
                                    (uint192 ret, uint nextOffset) = asUint192Unchecked(encoded, offset);
                                    return (bytes24(ret), nextOffset);
                                  }
                                  function asBytes24(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes24, uint) {
                                    (uint192 ret, uint nextOffset) = asUint192(encoded, offset);
                                    return (bytes24(ret), nextOffset);
                                  }
                                  function asUint200Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint200 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 25)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint200(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint200 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint200Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes25Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes25, uint) {
                                    (uint200 ret, uint nextOffset) = asUint200Unchecked(encoded, offset);
                                    return (bytes25(ret), nextOffset);
                                  }
                                  function asBytes25(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes25, uint) {
                                    (uint200 ret, uint nextOffset) = asUint200(encoded, offset);
                                    return (bytes25(ret), nextOffset);
                                  }
                                  function asUint208Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint208 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 26)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint208(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint208 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint208Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes26Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes26, uint) {
                                    (uint208 ret, uint nextOffset) = asUint208Unchecked(encoded, offset);
                                    return (bytes26(ret), nextOffset);
                                  }
                                  function asBytes26(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes26, uint) {
                                    (uint208 ret, uint nextOffset) = asUint208(encoded, offset);
                                    return (bytes26(ret), nextOffset);
                                  }
                                  function asUint216Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint216 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 27)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint216(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint216 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint216Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes27Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes27, uint) {
                                    (uint216 ret, uint nextOffset) = asUint216Unchecked(encoded, offset);
                                    return (bytes27(ret), nextOffset);
                                  }
                                  function asBytes27(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes27, uint) {
                                    (uint216 ret, uint nextOffset) = asUint216(encoded, offset);
                                    return (bytes27(ret), nextOffset);
                                  }
                                  function asUint224Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint224 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 28)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint224(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint224 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint224Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes28Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes28, uint) {
                                    (uint224 ret, uint nextOffset) = asUint224Unchecked(encoded, offset);
                                    return (bytes28(ret), nextOffset);
                                  }
                                  function asBytes28(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes28, uint) {
                                    (uint224 ret, uint nextOffset) = asUint224(encoded, offset);
                                    return (bytes28(ret), nextOffset);
                                  }
                                  function asUint232Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint232 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 29)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint232(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint232 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint232Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes29Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes29, uint) {
                                    (uint232 ret, uint nextOffset) = asUint232Unchecked(encoded, offset);
                                    return (bytes29(ret), nextOffset);
                                  }
                                  function asBytes29(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes29, uint) {
                                    (uint232 ret, uint nextOffset) = asUint232(encoded, offset);
                                    return (bytes29(ret), nextOffset);
                                  }
                                  function asUint240Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint240 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 30)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint240(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint240 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint240Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes30Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes30, uint) {
                                    (uint240 ret, uint nextOffset) = asUint240Unchecked(encoded, offset);
                                    return (bytes30(ret), nextOffset);
                                  }
                                  function asBytes30(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes30, uint) {
                                    (uint240 ret, uint nextOffset) = asUint240(encoded, offset);
                                    return (bytes30(ret), nextOffset);
                                  }
                                  function asUint248Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint248 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 31)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint248(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint248 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint248Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes31Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes31, uint) {
                                    (uint248 ret, uint nextOffset) = asUint248Unchecked(encoded, offset);
                                    return (bytes31(ret), nextOffset);
                                  }
                                  function asBytes31(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes31, uint) {
                                    (uint248 ret, uint nextOffset) = asUint248(encoded, offset);
                                    return (bytes31(ret), nextOffset);
                                  }
                                  function asUint256Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint256 ret, uint nextOffset) {
                                    assembly ("memory-safe") {
                                      nextOffset := add(offset, 32)
                                      ret := mload(add(encoded, nextOffset))
                                    }
                                    return (ret, nextOffset);
                                  }
                                  function asUint256(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (uint256 ret, uint nextOffset) {
                                    (ret, nextOffset) = asUint256Unchecked(encoded, offset);
                                    checkBound(nextOffset, encoded.length);
                                  }
                                  function asBytes32Unchecked(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes32, uint) {
                                    (uint256 ret, uint nextOffset) = asUint256Unchecked(encoded, offset);
                                    return (bytes32(ret), nextOffset);
                                  }
                                  function asBytes32(
                                    bytes memory encoded,
                                    uint offset
                                  ) internal pure returns (bytes32, uint) {
                                    (uint256 ret, uint nextOffset) = asUint256(encoded, offset);
                                    return (bytes32(ret), nextOffset);
                                  }
                                }
                                

                                File 2 of 3: Wormhole
                                // contracts/Wormhole.sol
                                // SPDX-License-Identifier: Apache 2
                                pragma solidity ^0.8.0;
                                import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
                                contract Wormhole is ERC1967Proxy {
                                    constructor (address implementation, bytes memory initData) ERC1967Proxy(
                                        implementation,
                                        initData
                                    ) { }
                                }// SPDX-License-Identifier: MIT
                                pragma solidity ^0.8.0;
                                import "../Proxy.sol";
                                import "./ERC1967Upgrade.sol";
                                /**
                                 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
                                 * implementation address that can be changed. This address is stored in storage in the location specified by
                                 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
                                 * implementation behind the proxy.
                                 */
                                contract ERC1967Proxy is Proxy, ERC1967Upgrade {
                                    /**
                                     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                                     *
                                     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                                     * function call, and allows initializating the storage of the proxy like a Solidity constructor.
                                     */
                                    constructor(address _logic, bytes memory _data) payable {
                                        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
                                        _upgradeToAndCall(_logic, _data, false);
                                    }
                                    /**
                                     * @dev Returns the current implementation address.
                                     */
                                    function _implementation() internal view virtual override returns (address impl) {
                                        return ERC1967Upgrade._getImplementation();
                                    }
                                }
                                // SPDX-License-Identifier: MIT
                                pragma solidity ^0.8.2;
                                import "../beacon/IBeacon.sol";
                                import "../../utils/Address.sol";
                                import "../../utils/StorageSlot.sol";
                                /**
                                 * @dev This abstract contract provides getters and event emitting update functions for
                                 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
                                 *
                                 * _Available since v4.1._
                                 *
                                 * @custom:oz-upgrades-unsafe-allow delegatecall
                                 */
                                abstract contract ERC1967Upgrade {
                                    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                                    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                                    /**
                                     * @dev Storage slot with the address of the current implementation.
                                     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                                     * validated in the constructor.
                                     */
                                    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                                    /**
                                     * @dev Emitted when the implementation is upgraded.
                                     */
                                    event Upgraded(address indexed implementation);
                                    /**
                                     * @dev Returns the current implementation address.
                                     */
                                    function _getImplementation() internal view returns (address) {
                                        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                                    }
                                    /**
                                     * @dev Stores a new address in the EIP1967 implementation slot.
                                     */
                                    function _setImplementation(address newImplementation) private {
                                        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                                        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                                    }
                                    /**
                                     * @dev Perform implementation upgrade
                                     *
                                     * Emits an {Upgraded} event.
                                     */
                                    function _upgradeTo(address newImplementation) internal {
                                        _setImplementation(newImplementation);
                                        emit Upgraded(newImplementation);
                                    }
                                    /**
                                     * @dev Perform implementation upgrade with additional setup call.
                                     *
                                     * Emits an {Upgraded} event.
                                     */
                                    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
                                        _setImplementation(newImplementation);
                                        emit Upgraded(newImplementation);
                                        if (data.length > 0 || forceCall) {
                                            Address.functionDelegateCall(newImplementation, data);
                                        }
                                    }
                                    /**
                                     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                                     *
                                     * Emits an {Upgraded} event.
                                     */
                                    function _upgradeToAndCallSecure(address newImplementation, bytes memory data, bool forceCall) internal {
                                        address oldImplementation = _getImplementation();
                                        // Initial upgrade and setup call
                                        _setImplementation(newImplementation);
                                        if (data.length > 0 || forceCall) {
                                            Address.functionDelegateCall(newImplementation, data);
                                        }
                                        // Perform rollback test if not already in progress
                                        StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT);
                                        if (!rollbackTesting.value) {
                                            // Trigger rollback using upgradeTo from the new implementation
                                            rollbackTesting.value = true;
                                            Address.functionDelegateCall(
                                                newImplementation,
                                                abi.encodeWithSignature(
                                                    "upgradeTo(address)",
                                                    oldImplementation
                                                )
                                            );
                                            rollbackTesting.value = false;
                                            // Check rollback was effective
                                            require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
                                            // Finally reset to the new implementation and log the upgrade
                                            _setImplementation(newImplementation);
                                            emit Upgraded(newImplementation);
                                        }
                                    }
                                    /**
                                     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                                     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                                     *
                                     * Emits a {BeaconUpgraded} event.
                                     */
                                    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
                                        _setBeacon(newBeacon);
                                        emit BeaconUpgraded(newBeacon);
                                        if (data.length > 0 || forceCall) {
                                            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                                        }
                                    }
                                    /**
                                     * @dev Storage slot with the admin of the contract.
                                     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                                     * validated in the constructor.
                                     */
                                    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                                    /**
                                     * @dev Emitted when the admin account has changed.
                                     */
                                    event AdminChanged(address previousAdmin, address newAdmin);
                                    /**
                                     * @dev Returns the current admin.
                                     */
                                    function _getAdmin() internal view returns (address) {
                                        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
                                    }
                                    /**
                                     * @dev Stores a new address in the EIP1967 admin slot.
                                     */
                                    function _setAdmin(address newAdmin) private {
                                        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                                        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                                    }
                                    /**
                                     * @dev Changes the admin of the proxy.
                                     *
                                     * Emits an {AdminChanged} event.
                                     */
                                    function _changeAdmin(address newAdmin) internal {
                                        emit AdminChanged(_getAdmin(), newAdmin);
                                        _setAdmin(newAdmin);
                                    }
                                    /**
                                     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                                     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                                     */
                                    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                                    /**
                                     * @dev Emitted when the beacon is upgraded.
                                     */
                                    event BeaconUpgraded(address indexed beacon);
                                    /**
                                     * @dev Returns the current beacon.
                                     */
                                    function _getBeacon() internal view returns (address) {
                                        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
                                    }
                                    /**
                                     * @dev Stores a new beacon in the EIP1967 beacon slot.
                                     */
                                    function _setBeacon(address newBeacon) private {
                                        require(
                                            Address.isContract(newBeacon),
                                            "ERC1967: new beacon is not a contract"
                                        );
                                        require(
                                            Address.isContract(IBeacon(newBeacon).implementation()),
                                            "ERC1967: beacon implementation is not a contract"
                                        );
                                        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                                    }
                                }
                                // SPDX-License-Identifier: MIT
                                pragma solidity ^0.8.0;
                                /**
                                 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
                                 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
                                 * be specified by overriding the virtual {_implementation} function.
                                 *
                                 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
                                 * different contract through the {_delegate} function.
                                 *
                                 * The success and return data of the delegated call will be returned back to the caller of the proxy.
                                 */
                                abstract contract Proxy {
                                    /**
                                     * @dev Delegates the current call to `implementation`.
                                     *
                                     * This function does not return to its internall call site, it will return directly to the external caller.
                                     */
                                    function _delegate(address implementation) internal virtual {
                                        // solhint-disable-next-line no-inline-assembly
                                        assembly {
                                            // Copy msg.data. We take full control of memory in this inline assembly
                                            // block because it will not return to Solidity code. We overwrite the
                                            // Solidity scratch pad at memory position 0.
                                            calldatacopy(0, 0, calldatasize())
                                            // Call the implementation.
                                            // out and outsize are 0 because we don't know the size yet.
                                            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                                            // Copy the returned data.
                                            returndatacopy(0, 0, returndatasize())
                                            switch result
                                            // delegatecall returns 0 on error.
                                            case 0 { revert(0, returndatasize()) }
                                            default { return(0, returndatasize()) }
                                        }
                                    }
                                    /**
                                     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                                     * and {_fallback} should delegate.
                                     */
                                    function _implementation() internal view virtual returns (address);
                                    /**
                                     * @dev Delegates the current call to the address returned by `_implementation()`.
                                     *
                                     * This function does not return to its internall call site, it will return directly to the external caller.
                                     */
                                    function _fallback() internal virtual {
                                        _beforeFallback();
                                        _delegate(_implementation());
                                    }
                                    /**
                                     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                                     * function in the contract matches the call data.
                                     */
                                    fallback () external payable virtual {
                                        _fallback();
                                    }
                                    /**
                                     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                                     * is empty.
                                     */
                                    receive () external payable virtual {
                                        _fallback();
                                    }
                                    /**
                                     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                                     * call, or as part of the Solidity `fallback` or `receive` functions.
                                     *
                                     * If overriden should call `super._beforeFallback()`.
                                     */
                                    function _beforeFallback() internal virtual {
                                    }
                                }
                                // SPDX-License-Identifier: MIT
                                pragma solidity ^0.8.0;
                                /**
                                 * @dev This is the interface that {BeaconProxy} expects of its beacon.
                                 */
                                interface IBeacon {
                                    /**
                                     * @dev Must return an address that can be used as a delegate call target.
                                     *
                                     * {BeaconProxy} will check that this address is a contract.
                                     */
                                    function implementation() external view returns (address);
                                }
                                // SPDX-License-Identifier: MIT
                                pragma solidity ^0.8.0;
                                /**
                                 * @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
                                     * ====
                                     */
                                    function isContract(address account) internal view returns (bool) {
                                        // This method relies on extcodesize, which returns 0 for contracts in
                                        // construction, since the code is only stored at the end of the
                                        // constructor execution.
                                        uint256 size;
                                        // solhint-disable-next-line no-inline-assembly
                                        assembly { size := extcodesize(account) }
                                        return size > 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");
                                        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                                        (bool success, ) = recipient.call{ value: amount }("");
                                        require(success, "Address: unable to send value, recipient may have reverted");
                                    }
                                    /**
                                     * @dev Performs a Solidity function call using a low level `call`. A
                                     * plain`call` is an unsafe replacement for a function call: use this
                                     * function instead.
                                     *
                                     * If `target` reverts with a revert reason, it is bubbled up by this
                                     * function (like regular Solidity function calls).
                                     *
                                     * Returns the raw returned data. To convert to the expected return value,
                                     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                                     *
                                     * Requirements:
                                     *
                                     * - `target` must be a contract.
                                     * - calling `target` with `data` must not revert.
                                     *
                                     * _Available since v3.1._
                                     */
                                    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                                      return functionCall(target, data, "Address: low-level call failed");
                                    }
                                    /**
                                     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                                     * `errorMessage` as a fallback revert reason when `target` reverts.
                                     *
                                     * _Available since v3.1._
                                     */
                                    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                                        return functionCallWithValue(target, data, 0, errorMessage);
                                    }
                                    /**
                                     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                                     * but also transferring `value` wei to `target`.
                                     *
                                     * Requirements:
                                     *
                                     * - the calling contract must have an ETH balance of at least `value`.
                                     * - the called Solidity function must be `payable`.
                                     *
                                     * _Available since v3.1._
                                     */
                                    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                                        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                                    }
                                    /**
                                     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                                     * with `errorMessage` as a fallback revert reason when `target` reverts.
                                     *
                                     * _Available since v3.1._
                                     */
                                    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                                        require(address(this).balance >= value, "Address: insufficient balance for call");
                                        require(isContract(target), "Address: call to non-contract");
                                        // solhint-disable-next-line avoid-low-level-calls
                                        (bool success, bytes memory returndata) = target.call{ value: value }(data);
                                        return _verifyCallResult(success, returndata, errorMessage);
                                    }
                                    /**
                                     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                                     * but performing a static call.
                                     *
                                     * _Available since v3.3._
                                     */
                                    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                                        return functionStaticCall(target, data, "Address: low-level static call failed");
                                    }
                                    /**
                                     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                                     * but performing a static call.
                                     *
                                     * _Available since v3.3._
                                     */
                                    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                                        require(isContract(target), "Address: static call to non-contract");
                                        // solhint-disable-next-line avoid-low-level-calls
                                        (bool success, bytes memory returndata) = target.staticcall(data);
                                        return _verifyCallResult(success, returndata, errorMessage);
                                    }
                                    /**
                                     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                                     * but performing a delegate call.
                                     *
                                     * _Available since v3.4._
                                     */
                                    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                                        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                                    }
                                    /**
                                     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                                     * but performing a delegate call.
                                     *
                                     * _Available since v3.4._
                                     */
                                    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                                        require(isContract(target), "Address: delegate call to non-contract");
                                        // solhint-disable-next-line avoid-low-level-calls
                                        (bool success, bytes memory returndata) = target.delegatecall(data);
                                        return _verifyCallResult(success, returndata, errorMessage);
                                    }
                                    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                                        if (success) {
                                            return returndata;
                                        } else {
                                            // Look for revert reason and bubble it up if present
                                            if (returndata.length > 0) {
                                                // The easiest way to bubble the revert reason is using memory via assembly
                                                // solhint-disable-next-line no-inline-assembly
                                                assembly {
                                                    let returndata_size := mload(returndata)
                                                    revert(add(32, returndata), returndata_size)
                                                }
                                            } else {
                                                revert(errorMessage);
                                            }
                                        }
                                    }
                                }
                                // SPDX-License-Identifier: MIT
                                pragma solidity ^0.8.0;
                                /**
                                 * @dev Library for reading and writing primitive types to specific storage slots.
                                 *
                                 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
                                 * This library helps with reading and writing to such slots without the need for inline assembly.
                                 *
                                 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
                                 *
                                 * Example usage to set ERC1967 implementation slot:
                                 * ```
                                 * contract ERC1967 {
                                 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                                 *
                                 *     function _getImplementation() internal view returns (address) {
                                 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                                 *     }
                                 *
                                 *     function _setImplementation(address newImplementation) internal {
                                 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                                 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                                 *     }
                                 * }
                                 * ```
                                 *
                                 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
                                 */
                                library StorageSlot {
                                    struct AddressSlot {
                                        address value;
                                    }
                                    struct BooleanSlot {
                                        bool value;
                                    }
                                    struct Bytes32Slot {
                                        bytes32 value;
                                    }
                                    struct Uint256Slot {
                                        uint256 value;
                                    }
                                    /**
                                     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                                     */
                                    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                                        assembly {
                                            r.slot := slot
                                        }
                                    }
                                    /**
                                     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                                     */
                                    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                                        assembly {
                                            r.slot := slot
                                        }
                                    }
                                    /**
                                     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                                     */
                                    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                                        assembly {
                                            r.slot := slot
                                        }
                                    }
                                    /**
                                     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                                     */
                                    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                                        assembly {
                                            r.slot := slot
                                        }
                                    }
                                }
                                

                                File 3 of 3: Executor
                                // SPDX-License-Identifier: Apache-2.0
                                pragma solidity ^0.8.13;
                                import "./interfaces/IExecutor.sol";
                                string constant executorVersion = "Executor-0.0.1";
                                contract Executor is IExecutor {
                                    string public constant EXECUTOR_VERSION = executorVersion;
                                    uint16 public immutable ourChain;
                                    constructor(uint16 _ourChain) {
                                        ourChain = _ourChain;
                                    }
                                    error QuoteSrcChainMismatch(uint16 quoteSrcChain, uint16 requestSrcChain);
                                    error QuoteDstChainMismatch(uint16 quoteDstChain, uint16 requestDstChain);
                                    error QuoteExpired(uint64 expiryTime);
                                    error NotAnEvmAddress(bytes32);
                                    function requestExecution(
                                        uint16 dstChain,
                                        bytes32 dstAddr,
                                        address refundAddr,
                                        bytes calldata signedQuoteBytes,
                                        bytes calldata requestBytes,
                                        bytes calldata relayInstructions
                                    ) public payable {
                                        {
                                            uint16 quoteSrcChain;
                                            uint16 quoteDstChain;
                                            uint64 expiryTime;
                                            assembly {
                                                quoteSrcChain := shr(240, calldataload(add(signedQuoteBytes.offset, 56)))
                                                quoteDstChain := shr(240, calldataload(add(signedQuoteBytes.offset, 58)))
                                                expiryTime := shr(192, calldataload(add(signedQuoteBytes.offset, 60)))
                                            }
                                            if (quoteSrcChain != ourChain) {
                                                revert QuoteSrcChainMismatch(quoteSrcChain, ourChain);
                                            }
                                            if (quoteDstChain != dstChain) {
                                                revert QuoteDstChainMismatch(quoteDstChain, dstChain);
                                            }
                                            if (expiryTime <= block.timestamp) {
                                                revert QuoteExpired(expiryTime);
                                            }
                                        }
                                        uint160 quoterAddress;
                                        bytes32 universalPayeeAddress;
                                        assembly {
                                            quoterAddress := shr(96, calldataload(add(signedQuoteBytes.offset, 4)))
                                            universalPayeeAddress := calldataload(add(signedQuoteBytes.offset, 24))
                                        }
                                        // Check if the higher 96 bits (left-most 12 bytes) are non-zero
                                        if (uint256(universalPayeeAddress) >> 160 != 0) {
                                            revert NotAnEvmAddress(universalPayeeAddress);
                                        }
                                        address payeeAddress = address(uint160(uint256(universalPayeeAddress)));
                                        payable(payeeAddress).transfer(msg.value);
                                        emit RequestForExecution(
                                            address(quoterAddress),
                                            msg.value,
                                            dstChain,
                                            dstAddr,
                                            refundAddr,
                                            signedQuoteBytes,
                                            requestBytes,
                                            relayInstructions
                                        );
                                    }
                                }
                                // 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;
                                }