ETH Price: $2,065.16 (+11.30%)

Transaction Decoder

Block:
23293923 at Sep-05-2025 02:28:35 AM +UTC
Transaction Fee:
0.000094975916365044 ETH $0.20
Gas Used:
117,052 Gas / 0.811399347 Gwei

Emitted Events:

198 0xc38e4e6a15593f908255214653d3d947ca1c2338.0x918554b6bd6e2895ce6553de5de0e1a69db5289aa0e4fe193a0dcd1f14347477( 0x918554b6bd6e2895ce6553de5de0e1a69db5289aa0e4fe193a0dcd1f14347477, ceaf382b34c07ca6f28aded69e4d244066b60822ec91d210a290f79543493081 )
199 MayanForwarder2.ForwardedEth( mayanProtocol=0xc38e4e6a15593f908255214653d3d947ca1c2338, protocolData=0xB866E1730000000000000000000000000F9A50C4D82FE7AA9255C0506F33E283859CD6FC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F296D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000068BA52E30000000000000000000000000F9A50C4D82FE7AA9255C0506F33E283859CD6FC000000000000000000000000000000000000000000000000000000000000001E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000245C4801A1C41210786C45C4CC338C59D5899229352427C916D592B9455B60671 )

Account State Difference:

  Address   Before After State Difference Code
0x0F9a50c4...3859Cd6fC
0.012075348579380129 Eth
Nonce: 96
0.001980372663015085 Eth
Nonce: 97
0.010094975916365044
(Titan Builder)
19.445098349026036488 Eth19.445156875026036488 Eth0.000058526
0x9b2A3B92...227bA6D09 5.482701454670905899 Eth5.482711454670905899 Eth0.00001
0xC38e4e6A...7CA1c2338
(Mayan: Swift)
13.863134225628748984 Eth13.873124225628748984 Eth0.00999

Execution Trace

ETH 0.01 MayanForwarderWithReferrer.forwardEth( forwarderData=0xB0F584FF000000000000000000000000C38E4E6A15593F908255214653D3D947CA1C2338000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001A4B866E1730000000000000000000000000F9A50C4D82FE7AA9255C0506F33E283859CD6FC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F296D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000068BA52E30000000000000000000000000F9A50C4D82FE7AA9255C0506F33E283859CD6FC000000000000000000000000000000000000000000000000000000000000001E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000245C4801A1C41210786C45C4CC338C59D5899229352427C916D592B9455B6067100000000000000000000000000000000000000000000000000000000, feeArgs=[{name:fee, type:uint256, order:1, indexed:false, value:10000000000000, valueString:10000000000000}, {name:payee, type:address, order:2, indexed:false, value:0x9b2A3B92b1D86938D3Ed37B0519952C227bA6D09, valueString:0x9b2A3B92b1D86938D3Ed37B0519952C227bA6D09}] )
  • ETH 0.00001 0x9b2a3b92b1d86938d3ed37b0519952c227ba6d09.CALL( )
  • ETH 0.00999 MayanForwarder2.forwardEth( mayanProtocol=0xC38e4e6A15593f908255214653d3D947CA1c2338, protocolData=0xB866E1730000000000000000000000000F9A50C4D82FE7AA9255C0506F33E283859CD6FC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F296D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000068BA52E30000000000000000000000000F9A50C4D82FE7AA9255C0506F33E283859CD6FC000000000000000000000000000000000000000000000000000000000000001E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000245C4801A1C41210786C45C4CC338C59D5899229352427C916D592B9455B60671 )
    • ETH 0.00999 Mayan: Swift.b866e173( )
      • 0xf93191d350117723dbeda5484a3b0996d285cecf.02fb1eec( )
      • Wormhole.STATICCALL( )
        • 0x3c3d457f1522d3540ab3325aa5f1864e34cba9d0.DELEGATECALL( )
        • Wormhole.STATICCALL( )
          • 0x3c3d457f1522d3540ab3325aa5f1864e34cba9d0.DELEGATECALL( )
            File 1 of 3: MayanForwarderWithReferrer
            // 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 "./interfaces/IMayanForwarderWithReferrer.sol";
            string constant MayanForwarderWithReferrerVersion = "MayanForwarderWithReferrer-0.0.1";
            /// @title MayanForwarderWithReferrer
            /// @author Wormhole Project Contributors.
            /// @notice The MayanForwarderWithReferrer contract is a shim contract that initiates a forward
            ///         or swap using the Mayan Forwarder contract and passes a fee to the specified referrer.
            contract MayanForwarderWithReferrer is IMayanForwarderWithReferrer {
                string public constant VERSION = MayanForwarderWithReferrerVersion;
                address public immutable mayanForwarder;
                constructor(address _mayanForwarder) {
                    assert(_mayanForwarder != address(0));
                    mayanForwarder = _mayanForwarder;
                }
                // ==================== External Interface ===============================================
                function forwardEth(bytes calldata forwarderData, FeeArgs calldata feeArgs) external payable {
                    // Don't need to custody the tokens in this contract.
                    // Transfer the fee to the referrer.
                    if (feeArgs.fee > 0) {
                        (bool transferSuccessful,) = payable(feeArgs.payee).call{value: feeArgs.fee}("");
                        if (!transferSuccessful) {
                            revert FeeTransferFailed(feeArgs.fee);
                        }
                    }
                    // Initiate the forward.
                    (bool success,) = mayanForwarder.call{value: msg.value - feeArgs.fee}(forwarderData);
                    require(success, "mayan forwarder call failed");
                    // Refund any excess value.
                    _refundBalance(msg.sender);
                }
                function forwardERC20(bytes calldata forwarderData, address tokenIn, uint256 amountIn, FeeArgs calldata feeArgs)
                    external
                    payable
                {
                    // Custody the tokens in this contract.
                    amountIn = _custodyTokens(tokenIn, amountIn);
                    // Transfer the fee to the referrer.
                    if (feeArgs.fee > 0) {
                        if (amountIn < feeArgs.fee) {
                            revert FeeTooLarge(amountIn, feeArgs.fee);
                        }
                        SafeERC20.safeTransfer(IERC20(tokenIn), feeArgs.payee, feeArgs.fee);
                    }
                    // Approve the forwarder to spend the tokens.
                    _maxApproveIfNeeded(tokenIn, mayanForwarder, amountIn);
                    // Initiate the forward.
                    (bool success,) = mayanForwarder.call{value: msg.value}(forwarderData);
                    require(success, "mayan forwarder call failed");
                    // Refund any excess value.
                    _refundBalance(msg.sender);
                }
                // 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));
                }
                function _refundBalance(address refundAddress) internal {
                    uint256 currentBalance = address(this).balance;
                    if (currentBalance > 0) {
                        (bool refundSuccessful,) = payable(refundAddress).call{value: currentBalance}("");
                        if (!refundSuccessful) {
                            revert RefundFailed(currentBalance);
                        }
                    }
                }
                /// @dev This is based on what is in the MayanForwarder contract here: https://github.com/mayan-finance/swap-bridge/blob/main/src/MayanForwarder.sol
                function _maxApproveIfNeeded(address tokenAddr, address spender, uint256 amount) internal {
                    IERC20 token = IERC20(tokenAddr);
                    uint256 currentAllowance = token.allowance(address(this), spender);
                    if (currentAllowance < amount) {
                        SafeERC20.safeApprove(token, spender, 0);
                        SafeERC20.safeApprove(token, spender, type(uint256).max);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Interface of the ERC20 standard as defined in the EIP.
             */
            interface IERC20 {
                /**
                 * @dev Emitted when `value` tokens are moved from one account (`from`) to
                 * another (`to`).
                 *
                 * Note that `value` may be zero.
                 */
                event Transfer(address indexed from, address indexed to, uint256 value);
                /**
                 * @dev Emitted when the allowance of a `spender` for an `owner` is set by
                 * a call to {approve}. `value` is the new allowance.
                 */
                event Approval(address indexed owner, address indexed spender, uint256 value);
                /**
                 * @dev Returns the amount of tokens in existence.
                 */
                function totalSupply() external view returns (uint256);
                /**
                 * @dev Returns the amount of tokens owned by `account`.
                 */
                function balanceOf(address account) external view returns (uint256);
                /**
                 * @dev Moves `amount` tokens from the caller's account to `to`.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transfer(address to, uint256 amount) external returns (bool);
                /**
                 * @dev Returns the remaining number of tokens that `spender` will be
                 * allowed to spend on behalf of `owner` through {transferFrom}. This is
                 * zero by default.
                 *
                 * This value changes when {approve} or {transferFrom} are called.
                 */
                function allowance(address owner, address spender) external view returns (uint256);
                /**
                 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * IMPORTANT: Beware that changing an allowance with this method brings the risk
                 * that someone may use both the old and the new allowance by unfortunate
                 * transaction ordering. One possible solution to mitigate this race
                 * condition is to first reduce the spender's allowance to 0 and set the
                 * desired value afterwards:
                 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                 *
                 * Emits an {Approval} event.
                 */
                function approve(address spender, uint256 amount) external returns (bool);
                /**
                 * @dev Moves `amount` tokens from `from` to `to` using the
                 * allowance mechanism. `amount` is then deducted from the caller's
                 * allowance.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transferFrom(
                    address from,
                    address to,
                    uint256 amount
                ) external returns (bool);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
            pragma solidity ^0.8.0;
            import "../IERC20.sol";
            import "../extensions/draft-IERC20Permit.sol";
            import "../../../utils/Address.sol";
            /**
             * @title SafeERC20
             * @dev Wrappers around ERC20 operations that throw on failure (when the token
             * contract returns false). Tokens that return no value (and instead revert or
             * throw on failure) are also supported, non-reverting calls are assumed to be
             * successful.
             * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
             * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
             */
            library SafeERC20 {
                using Address for address;
                function safeTransfer(
                    IERC20 token,
                    address to,
                    uint256 value
                ) internal {
                    _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
                }
                function safeTransferFrom(
                    IERC20 token,
                    address from,
                    address to,
                    uint256 value
                ) internal {
                    _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
                }
                /**
                 * @dev Deprecated. This function has issues similar to the ones found in
                 * {IERC20-approve}, and its usage is discouraged.
                 *
                 * Whenever possible, use {safeIncreaseAllowance} and
                 * {safeDecreaseAllowance} instead.
                 */
                function safeApprove(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    // safeApprove should only be called when setting an initial allowance,
                    // or when resetting it to zero. To increase and decrease it, use
                    // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                    require(
                        (value == 0) || (token.allowance(address(this), spender) == 0),
                        "SafeERC20: approve from non-zero to non-zero allowance"
                    );
                    _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
                }
                function safeIncreaseAllowance(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    uint256 newAllowance = token.allowance(address(this), spender) + value;
                    _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
                }
                function safeDecreaseAllowance(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    unchecked {
                        uint256 oldAllowance = token.allowance(address(this), spender);
                        require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
                        uint256 newAllowance = oldAllowance - value;
                        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
                    }
                }
                function safePermit(
                    IERC20Permit token,
                    address owner,
                    address spender,
                    uint256 value,
                    uint256 deadline,
                    uint8 v,
                    bytes32 r,
                    bytes32 s
                ) internal {
                    uint256 nonceBefore = token.nonces(owner);
                    token.permit(owner, spender, value, deadline, v, r, s);
                    uint256 nonceAfter = token.nonces(owner);
                    require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
                }
                /**
                 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
                 * on the return value: the return value is optional (but if data is returned, it must not be false).
                 * @param token The token targeted by the call.
                 * @param data The call data (encoded using abi.encode or one of its variants).
                 */
                function _callOptionalReturn(IERC20 token, bytes memory data) private {
                    // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
                    // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
                    // the target address contains contract code and also asserts for success in the low-level call.
                    bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
                    if (returndata.length > 0) {
                        // Return data is optional
                        require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
                    }
                }
            }
            // SPDX-License-Identifier: Apache 2
            pragma solidity ^0.8.19;
            struct FeeArgs {
                // The fee.
                uint256 fee;
                // To whom the fee should be paid (the "referrer").
                address payee;
            }
            interface IMayanForwarderWithReferrer {
                /// @notice Error when the fee is greater than the total amount.
                /// @dev Selector 0x359f998c.
                /// @param amountIn The amount passed in, which should include the fee.
                /// @param fee The fee amount.
                error FeeTooLarge(uint256 amountIn, uint256 fee);
                /// @notice Error when transferring the fee to the referrer fails.
                /// @dev Selector 0x7e802910.
                /// @param fee The fee amount.
                error FeeTransferFailed(uint256 fee);
                /// @notice Error when the refund to the sender fails.
                /// @dev Selector 0x2ca23714.
                /// @param refundAmount The refund amount.
                error RefundFailed(uint256 refundAmount);
                function forwardEth(bytes calldata forwarderData, FeeArgs calldata feeArgs) external payable;
                function forwardERC20(bytes calldata forwarderData, address tokenIn, uint256 amountIn, FeeArgs calldata feeArgs)
                    external
                    payable;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
             * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
             *
             * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
             * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
             * need to send a transaction, and thus is not required to hold Ether at all.
             */
            interface IERC20Permit {
                /**
                 * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
                 * given ``owner``'s signed approval.
                 *
                 * IMPORTANT: The same issues {IERC20-approve} has related to transaction
                 * ordering also apply here.
                 *
                 * Emits an {Approval} event.
                 *
                 * Requirements:
                 *
                 * - `spender` cannot be the zero address.
                 * - `deadline` must be a timestamp in the future.
                 * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
                 * over the EIP712-formatted function arguments.
                 * - the signature must use ``owner``'s current nonce (see {nonces}).
                 *
                 * For more information on the signature format, see the
                 * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
                 * section].
                 */
                function permit(
                    address owner,
                    address spender,
                    uint256 value,
                    uint256 deadline,
                    uint8 v,
                    bytes32 r,
                    bytes32 s
                ) external;
                /**
                 * @dev Returns the current nonce for `owner`. This value must be
                 * included whenever a signature is generated for {permit}.
                 *
                 * Every successful call to {permit} increases ``owner``'s nonce by one. This
                 * prevents a signature from being used multiple times.
                 */
                function nonces(address owner) external view returns (uint256);
                /**
                 * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
                 */
                // solhint-disable-next-line func-name-mixedcase
                function DOMAIN_SEPARATOR() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                 * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                 *
                 * _Available since v4.8._
                 */
                function verifyCallResultFromTarget(
                    address target,
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    if (success) {
                        if (returndata.length == 0) {
                            // only check isContract if the call was successful and the return data is empty
                            // otherwise we already know that it was a contract
                            require(isContract(target), "Address: call to non-contract");
                        }
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                /**
                 * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason or using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                function _revert(bytes memory returndata, string memory errorMessage) private pure {
                    // Look for revert reason and bubble it up if present
                    if (returndata.length > 0) {
                        // The easiest way to bubble the revert reason is using memory via assembly
                        /// @solidity memory-safe-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
            

            File 2 of 3: MayanForwarder2
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/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.9.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.9.3) (token/ERC20/utils/SafeERC20.sol)
            pragma solidity ^0.8.0;
            import "../IERC20.sol";
            import "../extensions/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;
                /**
                 * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
                 * non-reverting calls are assumed to be successful.
                 */
                function safeTransfer(IERC20 token, address to, uint256 value) internal {
                    _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
                }
                /**
                 * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
                 * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
                 */
                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));
                }
                /**
                 * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
                 * non-reverting calls are assumed to be successful.
                 */
                function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                    uint256 oldAllowance = token.allowance(address(this), spender);
                    _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
                }
                /**
                 * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
                 * non-reverting calls are assumed to be successful.
                 */
                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");
                        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
                    }
                }
                /**
                 * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
                 * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
                 * to be set to zero before setting it to a non-zero value, such as USDT.
                 */
                function forceApprove(IERC20 token, address spender, uint256 value) internal {
                    bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
                    if (!_callOptionalReturnBool(token, approvalCall)) {
                        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
                        _callOptionalReturn(token, approvalCall);
                    }
                }
                /**
                 * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
                 * Revert on invalid signature.
                 */
                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");
                    require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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).
                 *
                 * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
                 */
                function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
                    // 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 cannot use {Address-functionCall} here since this should return false
                    // and not revert is the subcall reverts.
                    (bool success, bytes memory returndata) = address(token).call(data);
                    return
                        success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.9.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
                 *
                 * Furthermore, `isContract` will also return true if the target contract within
                 * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
                 * which only has an effect at the end of a transaction.
                 * ====
                 *
                 * [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://consensys.net/diligence/blog/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.8.0/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: Unlicense
            /*
             * @title Solidity Bytes Arrays Utils
             * @author Gonçalo Sá <goncalo.sa@consensys.net>
             *
             * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
             *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
             */
            pragma solidity >=0.8.0 <0.9.0;
            library BytesLib {
                function concat(
                    bytes memory _preBytes,
                    bytes memory _postBytes
                )
                    internal
                    pure
                    returns (bytes memory)
                {
                    bytes memory tempBytes;
                    assembly {
                        // Get a location of some free memory and store it in tempBytes as
                        // Solidity does for memory variables.
                        tempBytes := mload(0x40)
                        // Store the length of the first bytes array at the beginning of
                        // the memory for tempBytes.
                        let length := mload(_preBytes)
                        mstore(tempBytes, length)
                        // Maintain a memory counter for the current write location in the
                        // temp bytes array by adding the 32 bytes for the array length to
                        // the starting location.
                        let mc := add(tempBytes, 0x20)
                        // Stop copying when the memory counter reaches the length of the
                        // first bytes array.
                        let end := add(mc, length)
                        for {
                            // Initialize a copy counter to the start of the _preBytes data,
                            // 32 bytes into its memory.
                            let cc := add(_preBytes, 0x20)
                        } lt(mc, end) {
                            // Increase both counters by 32 bytes each iteration.
                            mc := add(mc, 0x20)
                            cc := add(cc, 0x20)
                        } {
                            // Write the _preBytes data into the tempBytes memory 32 bytes
                            // at a time.
                            mstore(mc, mload(cc))
                        }
                        // Add the length of _postBytes to the current length of tempBytes
                        // and store it as the new length in the first 32 bytes of the
                        // tempBytes memory.
                        length := mload(_postBytes)
                        mstore(tempBytes, add(length, mload(tempBytes)))
                        // Move the memory counter back from a multiple of 0x20 to the
                        // actual end of the _preBytes data.
                        mc := end
                        // Stop copying when the memory counter reaches the new combined
                        // length of the arrays.
                        end := add(mc, length)
                        for {
                            let cc := add(_postBytes, 0x20)
                        } lt(mc, end) {
                            mc := add(mc, 0x20)
                            cc := add(cc, 0x20)
                        } {
                            mstore(mc, mload(cc))
                        }
                        // Update the free-memory pointer by padding our last write location
                        // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
                        // next 32 byte block, then round down to the nearest multiple of
                        // 32. If the sum of the length of the two arrays is zero then add
                        // one before rounding down to leave a blank 32 bytes (the length block with 0).
                        mstore(0x40, and(
                          add(add(end, iszero(add(length, mload(_preBytes)))), 31),
                          not(31) // Round down to the nearest 32 bytes.
                        ))
                    }
                    return tempBytes;
                }
                function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
                    assembly {
                        // Read the first 32 bytes of _preBytes storage, which is the length
                        // of the array. (We don't need to use the offset into the slot
                        // because arrays use the entire slot.)
                        let fslot := sload(_preBytes.slot)
                        // Arrays of 31 bytes or less have an even value in their slot,
                        // while longer arrays have an odd value. The actual length is
                        // the slot divided by two for odd values, and the lowest order
                        // byte divided by two for even values.
                        // If the slot is even, bitwise and the slot with 255 and divide by
                        // two to get the length. If the slot is odd, bitwise and the slot
                        // with -1 and divide by two.
                        let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
                        let mlength := mload(_postBytes)
                        let newlength := add(slength, mlength)
                        // slength can contain both the length and contents of the array
                        // if length < 32 bytes so let's prepare for that
                        // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                        switch add(lt(slength, 32), lt(newlength, 32))
                        case 2 {
                            // Since the new array still fits in the slot, we just need to
                            // update the contents of the slot.
                            // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                            sstore(
                                _preBytes.slot,
                                // all the modifications to the slot are inside this
                                // next block
                                add(
                                    // we can just add to the slot contents because the
                                    // bytes we want to change are the LSBs
                                    fslot,
                                    add(
                                        mul(
                                            div(
                                                // load the bytes from memory
                                                mload(add(_postBytes, 0x20)),
                                                // zero all bytes to the right
                                                exp(0x100, sub(32, mlength))
                                            ),
                                            // and now shift left the number of bytes to
                                            // leave space for the length in the slot
                                            exp(0x100, sub(32, newlength))
                                        ),
                                        // increase length by the double of the memory
                                        // bytes length
                                        mul(mlength, 2)
                                    )
                                )
                            )
                        }
                        case 1 {
                            // The stored value fits in the slot, but the combined value
                            // will exceed it.
                            // get the keccak hash to get the contents of the array
                            mstore(0x0, _preBytes.slot)
                            let sc := add(keccak256(0x0, 0x20), div(slength, 32))
                            // save new length
                            sstore(_preBytes.slot, add(mul(newlength, 2), 1))
                            // The contents of the _postBytes array start 32 bytes into
                            // the structure. Our first read should obtain the `submod`
                            // bytes that can fit into the unused space in the last word
                            // of the stored array. To get this, we read 32 bytes starting
                            // from `submod`, so the data we read overlaps with the array
                            // contents by `submod` bytes. Masking the lowest-order
                            // `submod` bytes allows us to add that value directly to the
                            // stored value.
                            let submod := sub(32, slength)
                            let mc := add(_postBytes, submod)
                            let end := add(_postBytes, mlength)
                            let mask := sub(exp(0x100, submod), 1)
                            sstore(
                                sc,
                                add(
                                    and(
                                        fslot,
                                        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                                    ),
                                    and(mload(mc), mask)
                                )
                            )
                            for {
                                mc := add(mc, 0x20)
                                sc := add(sc, 1)
                            } lt(mc, end) {
                                sc := add(sc, 1)
                                mc := add(mc, 0x20)
                            } {
                                sstore(sc, mload(mc))
                            }
                            mask := exp(0x100, sub(mc, end))
                            sstore(sc, mul(div(mload(mc), mask), mask))
                        }
                        default {
                            // get the keccak hash to get the contents of the array
                            mstore(0x0, _preBytes.slot)
                            // Start copying to the last used word of the stored array.
                            let sc := add(keccak256(0x0, 0x20), div(slength, 32))
                            // save new length
                            sstore(_preBytes.slot, add(mul(newlength, 2), 1))
                            // Copy over the first `submod` bytes of the new data as in
                            // case 1 above.
                            let slengthmod := mod(slength, 32)
                            let mlengthmod := mod(mlength, 32)
                            let submod := sub(32, slengthmod)
                            let mc := add(_postBytes, submod)
                            let end := add(_postBytes, mlength)
                            let mask := sub(exp(0x100, submod), 1)
                            sstore(sc, add(sload(sc), and(mload(mc), mask)))
                            for {
                                sc := add(sc, 1)
                                mc := add(mc, 0x20)
                            } lt(mc, end) {
                                sc := add(sc, 1)
                                mc := add(mc, 0x20)
                            } {
                                sstore(sc, mload(mc))
                            }
                            mask := exp(0x100, sub(mc, end))
                            sstore(sc, mul(div(mload(mc), mask), mask))
                        }
                    }
                }
                function slice(
                    bytes memory _bytes,
                    uint256 _start,
                    uint256 _length
                )
                    internal
                    pure
                    returns (bytes memory)
                {
                    require(_length + 31 >= _length, "slice_overflow");
                    require(_bytes.length >= _start + _length, "slice_outOfBounds");
                    bytes memory tempBytes;
                    assembly {
                        switch iszero(_length)
                        case 0 {
                            // Get a location of some free memory and store it in tempBytes as
                            // Solidity does for memory variables.
                            tempBytes := mload(0x40)
                            // The first word of the slice result is potentially a partial
                            // word read from the original array. To read it, we calculate
                            // the length of that partial word and start copying that many
                            // bytes into the array. The first word we copy will start with
                            // data we don't care about, but the last `lengthmod` bytes will
                            // land at the beginning of the contents of the new array. When
                            // we're done copying, we overwrite the full first word with
                            // the actual length of the slice.
                            let lengthmod := and(_length, 31)
                            // The multiplication in the next line is necessary
                            // because when slicing multiples of 32 bytes (lengthmod == 0)
                            // the following copy loop was copying the origin's length
                            // and then ending prematurely not copying everything it should.
                            let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                            let end := add(mc, _length)
                            for {
                                // The multiplication in the next line has the same exact purpose
                                // as the one above.
                                let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                            } lt(mc, end) {
                                mc := add(mc, 0x20)
                                cc := add(cc, 0x20)
                            } {
                                mstore(mc, mload(cc))
                            }
                            mstore(tempBytes, _length)
                            //update free-memory pointer
                            //allocating the array padded to 32 bytes like the compiler does now
                            mstore(0x40, and(add(mc, 31), not(31)))
                        }
                        //if we want a zero-length slice let's just return a zero-length array
                        default {
                            tempBytes := mload(0x40)
                            //zero out the 32 bytes slice we are about to return
                            //we need to do it because Solidity does not garbage collect
                            mstore(tempBytes, 0)
                            mstore(0x40, add(tempBytes, 0x20))
                        }
                    }
                    return tempBytes;
                }
                function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
                    require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
                    address tempAddress;
                    assembly {
                        tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
                    }
                    return tempAddress;
                }
                function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
                    require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
                    uint8 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x1), _start))
                    }
                    return tempUint;
                }
                function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
                    require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
                    uint16 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x2), _start))
                    }
                    return tempUint;
                }
                function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
                    require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
                    uint32 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x4), _start))
                    }
                    return tempUint;
                }
                function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
                    require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
                    uint64 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x8), _start))
                    }
                    return tempUint;
                }
                function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
                    require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
                    uint96 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0xc), _start))
                    }
                    return tempUint;
                }
                function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
                    require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
                    uint128 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x10), _start))
                    }
                    return tempUint;
                }
                function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
                    require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
                    uint256 tempUint;
                    assembly {
                        tempUint := mload(add(add(_bytes, 0x20), _start))
                    }
                    return tempUint;
                }
                function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
                    require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
                    bytes32 tempBytes32;
                    assembly {
                        tempBytes32 := mload(add(add(_bytes, 0x20), _start))
                    }
                    return tempBytes32;
                }
                function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
                    bool success = true;
                    assembly {
                        let length := mload(_preBytes)
                        // if lengths don't match the arrays are not equal
                        switch eq(length, mload(_postBytes))
                        case 1 {
                            // cb is a circuit breaker in the for loop since there's
                            //  no said feature for inline assembly loops
                            // cb = 1 - don't breaker
                            // cb = 0 - break
                            let cb := 1
                            let mc := add(_preBytes, 0x20)
                            let end := add(mc, length)
                            for {
                                let cc := add(_postBytes, 0x20)
                            // the next line is the loop condition:
                            // while(uint256(mc < end) + cb == 2)
                            } eq(add(lt(mc, end), cb), 2) {
                                mc := add(mc, 0x20)
                                cc := add(cc, 0x20)
                            } {
                                // if any of these checks fails then arrays are not equal
                                if iszero(eq(mload(mc), mload(cc))) {
                                    // unsuccess:
                                    success := 0
                                    cb := 0
                                }
                            }
                        }
                        default {
                            // unsuccess:
                            success := 0
                        }
                    }
                    return success;
                }
                function equalStorage(
                    bytes storage _preBytes,
                    bytes memory _postBytes
                )
                    internal
                    view
                    returns (bool)
                {
                    bool success = true;
                    assembly {
                        // we know _preBytes_offset is 0
                        let fslot := sload(_preBytes.slot)
                        // Decode the length of the stored array like in concatStorage().
                        let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
                        let mlength := mload(_postBytes)
                        // if lengths don't match the arrays are not equal
                        switch eq(slength, mlength)
                        case 1 {
                            // slength can contain both the length and contents of the array
                            // if length < 32 bytes so let's prepare for that
                            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                            if iszero(iszero(slength)) {
                                switch lt(slength, 32)
                                case 1 {
                                    // blank the last byte which is the length
                                    fslot := mul(div(fslot, 0x100), 0x100)
                                    if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                                        // unsuccess:
                                        success := 0
                                    }
                                }
                                default {
                                    // cb is a circuit breaker in the for loop since there's
                                    //  no said feature for inline assembly loops
                                    // cb = 1 - don't breaker
                                    // cb = 0 - break
                                    let cb := 1
                                    // get the keccak hash to get the contents of the array
                                    mstore(0x0, _preBytes.slot)
                                    let sc := keccak256(0x0, 0x20)
                                    let mc := add(_postBytes, 0x20)
                                    let end := add(mc, mlength)
                                    // the next line is the loop condition:
                                    // while(uint256(mc < end) + cb == 2)
                                    for {} eq(add(lt(mc, end), cb), 2) {
                                        sc := add(sc, 1)
                                        mc := add(mc, 0x20)
                                    } {
                                        if iszero(eq(sload(sc), mload(mc))) {
                                            // unsuccess:
                                            success := 0
                                            cb := 0
                                        }
                                    }
                                }
                            }
                        }
                        default {
                            // unsuccess:
                            success := 0
                        }
                    }
                    return success;
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
            import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
            import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
            import "./libs/BytesLib.sol";
            contract MayanForwarder2 {
            \tusing SafeERC20 for IERC20;
            \tusing BytesLib for bytes;
            \tevent SwapAndForwarded(uint256 amount);
            \taddress public guardian;
            \taddress public nextGuardian;
            \tmapping(address => bool) public swapProtocols;
            \tmapping(address => bool) public mayanProtocols;
            \tevent ForwardedEth(address mayanProtocol, bytes protocolData);
            \tevent ForwardedERC20(address token, uint256 amount, address mayanProtocol, bytes protocolData);
            \tevent SwapAndForwardedEth(uint256 amountIn, address swapProtocol, address middleToken, uint256 middleAmount, address mayanProtocol, bytes mayanData);
            \tevent SwapAndForwardedERC20(address tokenIn, uint256 amountIn, address swapProtocol, address middleToken, uint256 middleAmount, address mayanProtocol, bytes mayanData);
            \terror UnsupportedProtocol();
            \tstruct PermitParams {
            \t\tuint256 value;
            \t\tuint256 deadline;
            \t\tuint8 v;
            \t\tbytes32 r;
            \t\tbytes32 s;
            \t}
            \tconstructor(address _guardian, address[] memory _swapProtocols, address[] memory _mayanProtocols) {
            \t\tguardian = _guardian;
            \t\tfor (uint256 i = 0; i < _swapProtocols.length; i++) {
            \t\t\tswapProtocols[_swapProtocols[i]] = true;
            \t\t}
            \t\tfor (uint256 i = 0; i < _mayanProtocols.length; i++) {
            \t\t\tmayanProtocols[_mayanProtocols[i]] = true;
            \t\t}
            \t}
            \tfunction forwardEth(
            \t\taddress mayanProtocol,
            \t\tbytes calldata protocolData
            \t) external payable {
            \t\tif (!mayanProtocols[mayanProtocol]) {
            \t\t\trevert UnsupportedProtocol();
            \t\t}
            \t\t(bool success, ) = mayanProtocol.call{value: msg.value}(protocolData);
            \t\trequire(success, "mayan protocol call failed");
            \t\temit ForwardedEth(mayanProtocol, protocolData);
            \t}
            \t
            \tfunction forwardERC20(
            \t\taddress tokenIn,
            \t\tuint256 amountIn,
            \t\tPermitParams calldata permitParams,
            \t\taddress mayanProtocol,
            \t\tbytes calldata protocolData
            \t\t) external payable {
            \t\tif (!mayanProtocols[mayanProtocol]) {
            \t\t\trevert UnsupportedProtocol();
            \t\t}
            \t\tpullTokenIn(tokenIn, amountIn, permitParams);
            \t\tmaxApproveIfNeeded(tokenIn, mayanProtocol, amountIn);
            \t\t(bool success, ) = mayanProtocol.call{value: msg.value}(protocolData);
            \t\trequire(success, "mayan protocol call failed");
            \t\temit ForwardedERC20(tokenIn, amountIn, mayanProtocol, protocolData);
            \t}
            \tfunction swapAndForwardEth(
            \t\tuint256 amountIn,
            \t\taddress swapProtocol,
            \t\tbytes calldata swapData,
            \t\taddress middleToken,
            \t\tuint256 minMiddleAmount,
            \t\taddress mayanProtocol,
            \t\tbytes calldata mayanData
            \t) external payable {
            \t\tif (!swapProtocols[swapProtocol] || !mayanProtocols[mayanProtocol]) {
            \t\t\trevert UnsupportedProtocol();
            \t\t}
            \t\trequire(middleToken != address(0), "middleToken cannot be zero address");
            \t\trequire(msg.value >= amountIn, "insufficient amountIn");
            \t\tuint256 middleAmount = IERC20(middleToken).balanceOf(address(this));
            \t\t(bool success, ) = swapProtocol.call{value: amountIn}(swapData);
            \t\trequire(success, "swap call failed");
            \t\tmiddleAmount = IERC20(middleToken).balanceOf(address(this)) - middleAmount;
            \t\trequire(middleAmount >= minMiddleAmount, "insufficient middle token");
            \t\tmaxApproveIfNeeded(middleToken, mayanProtocol, middleAmount);
            \t\tbytes memory modifiedData = replaceMiddleAmount(mayanData, middleAmount);
            \t\t(success, ) = mayanProtocol.call{value: msg.value - amountIn}(modifiedData);
            \t\trequire(success, "mayan protocol call failed");
            \t\temit SwapAndForwardedEth(amountIn, swapProtocol, middleToken, middleAmount, mayanProtocol, mayanData);
            \t}
            \tfunction swapAndForwardERC20(
            \t\taddress tokenIn,
            \t\tuint256 amountIn,
            \t\tPermitParams calldata permitParams,
            \t\taddress swapProtocol,
            \t\tbytes calldata swapData,
            \t\taddress middleToken,
            \t\tuint256 minMiddleAmount,
            \t\taddress mayanProtocol,
            \t\tbytes calldata mayanData
            \t) external payable {
            \t\tif (!swapProtocols[swapProtocol] || !mayanProtocols[mayanProtocol]) {
            \t\t\trevert UnsupportedProtocol();
            \t\t}
            \t\trequire(tokenIn != middleToken, "tokenIn and tokenOut must be different");
            \t\tuint256 amountBefore = IERC20(tokenIn).balanceOf(address(this));
            \t\tpullTokenIn(tokenIn, amountIn, permitParams);
            \t\tuint256 middleAmount;
            \t\tif (middleToken != address(0)) {
            \t\t\tmiddleAmount = IERC20(middleToken).balanceOf(address(this));
            \t\t} else {
            \t\t\tmiddleAmount = address(this).balance;
            \t\t}
            \t\tmaxApproveIfNeeded(tokenIn, swapProtocol, amountIn);
            \t\t(bool success, ) = swapProtocol.call{value: 0}(swapData);
            \t\trequire(success, "swap protocol call failed");
            \t\tif (middleToken != address(0)) {
            \t\t\tmiddleAmount = IERC20(middleToken).balanceOf(address(this)) - middleAmount;
            \t\t} else {
            \t\t\tmiddleAmount = address(this).balance - middleAmount;
            \t\t}
            \t\trequire(middleAmount >= minMiddleAmount, "insufficient middle token");
            \t\tuint256 val = msg.value;
            \t\tif (middleToken == address(0)) {
            \t\t\tval += middleAmount;
            \t\t} else {
            \t\t\tmaxApproveIfNeeded(middleToken, mayanProtocol, middleAmount);
            \t\t}
            \t\t(success, ) = mayanProtocol.call{value: val}(middleToken == address(0) ? mayanData : replaceMiddleAmount(mayanData, middleAmount));
            \t\trequire(success, "mayan protocol call failed");
            \t\ttransferBackRemaining(tokenIn, amountBefore);
            \t\temit SwapAndForwardedERC20(tokenIn, amountIn, swapProtocol, middleToken, middleAmount, mayanProtocol, mayanData);
            \t}
            \tfunction replaceMiddleAmount(bytes calldata mayanData, uint256 middleAmount) internal pure returns(bytes memory) {
            \t\trequire(mayanData.length >= 68, "Mayan data too short");
            \t\tbytes memory modifiedData = new bytes(mayanData.length);
            \t\t// Copy the function selector and token in
            \t\tfor (uint i = 0; i < 36; i++) {
            \t\t\tmodifiedData[i] = mayanData[i];
            \t\t}
            \t\t// Encode the amount and place it into the modified call data
            \t\t// Starting from byte 36 to byte 67 (32 bytes for uint256)
            \t\tbytes memory encodedAmount = abi.encode(middleAmount);
            \t\tfor (uint i = 0; i < 32; i++) {
            \t\t\tmodifiedData[i + 36] = encodedAmount[i];
            \t\t}
            \t\t// Copy the rest of the original data after the first argument
            \t\tfor (uint i = 68; i < mayanData.length; i++) {
            \t\t\tmodifiedData[i] = mayanData[i];
            \t\t}
            \t\treturn modifiedData;
            \t}
            \tfunction maxApproveIfNeeded(address tokenAddr, address spender, uint256 amount) internal {
            \t\tIERC20 token = IERC20(tokenAddr);
            \t\tuint256 currentAllowance = token.allowance(address(this), spender);
            \t\tif (currentAllowance < amount) {
            \t\t\ttoken.safeApprove(spender, 0);
            \t\t\ttoken.safeApprove(spender, type(uint256).max);
            \t\t}
            \t}
            \tfunction execPermit(
            \t\taddress token,
            \t\taddress owner,
            \t\tPermitParams calldata permitParams
            \t) internal {
            \t\tIERC20Permit(token).permit(
            \t\t\towner,
            \t\t\taddress(this),
            \t\t\tpermitParams.value,
            \t\t\tpermitParams.deadline,
            \t\t\tpermitParams.v,
            \t\t\tpermitParams.r,
            \t\t\tpermitParams.s
            \t\t);
            \t}
            \tfunction pullTokenIn(
            \t\taddress tokenIn,
            \t\tuint256 amountIn,
            \t\tPermitParams calldata permitParams
            \t) internal {
            \t\tuint256 allowance = IERC20(tokenIn).allowance(msg.sender, address(this));
            \t\tif (allowance < amountIn) {
            \t\t\texecPermit(tokenIn, msg.sender, permitParams);
            \t\t}
            \t\tIERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
            \t}
            \tfunction transferBackRemaining(address token, uint256 amountBefore) internal {
            \t\tuint256 remaining = IERC20(token).balanceOf(address(this));
            \t\tif (remaining > amountBefore) {
            \t\t\tIERC20(token).safeTransfer(msg.sender, remaining - amountBefore);
            \t\t}
            \t}
            \tfunction rescueToken(address token, uint256 amount, address to) public {
            \t\trequire(msg.sender == guardian, 'only guardian');
            \t\tIERC20(token).safeTransfer(to, amount);
            \t}
            \tfunction rescueEth(uint256 amount, address payable to) public {
            \t\trequire(msg.sender == guardian, 'only guardian');
            \t\trequire(to != address(0), 'transfer to the zero address');
            \t\t(bool success, ) = payable(to).call{value: amount}('');
            \t\trequire(success, 'payment failed');
            \t}
            \tfunction changeGuardian(address newGuardian) public {
            \t\trequire(msg.sender == guardian, 'only guardian');
            \t\tnextGuardian = newGuardian;
            \t}
            \tfunction claimGuardian() public {
            \t\trequire(msg.sender == nextGuardian, 'only next guardian');
            \t\tguardian = nextGuardian;
            \t}
            \tfunction setSwapProtocol(address swapProtocol, bool enabled) public {
            \t\trequire(msg.sender == guardian, 'only guardian');
            \t\tswapProtocols[swapProtocol] = enabled;
            \t}
            \tfunction setMayanProtocol(address mayanProtocol, bool enabled) public {
            \t\trequire(msg.sender == guardian, 'only guardian');
            \t\tmayanProtocols[mayanProtocol] = enabled;
            \t}
            \treceive() external payable {}
            }

            File 3 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
                    }
                }
            }