ETH Price: $1,869.54 (-12.80%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60e06040237342442025-11-05 16:19:5992 days ago1762359599  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Contract Source Code Verified (Exact Match)

Contract Name:
Passage

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
No with 200 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

import {PassagePermit2} from "./PassagePermit2.sol";
import {UsesPermit2} from "../UsesPermit2.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol";
import {ReentrancyGuardTransient} from "openzeppelin-contracts/contracts/utils/ReentrancyGuardTransient.sol";

/// @notice A contract deployed to Host chain that allows tokens to enter the rollup.
contract Passage is PassagePermit2, ReentrancyGuardTransient {
    using SafeERC20 for IERC20;
    using Address for address payable;

    /// @notice The chainId of rollup that Ether will be sent to by default when entering the rollup via fallback() or receive().
    uint256 public immutable defaultRollupChainId;

    /// @notice The address that is allowed to withdraw funds from the contract.
    address public immutable tokenAdmin;

    /// @notice tokenAddress => whether new EnterToken events are currently allowed for that token.
    mapping(address => bool) public canEnter;

    /// @notice Thrown when attempting to call admin functions if not the token admin.
    error OnlyTokenAdmin();

    /// @notice Thrown when attempting to enter the rollup with an ERC20 token that is not currently allowed.
    error DisallowedEnter(address token);

    /// @notice Emitted when Ether enters the rollup.
    /// @param rollupChainId - The chainId of the destination rollup.
    /// @param rollupRecipient - The recipient of Ether on the rollup.
    /// @param amount - The amount of Ether entering the rollup.
    event Enter(uint256 indexed rollupChainId, address indexed rollupRecipient, uint256 amount);

    /// @notice Emitted when ERC20 tokens enter the rollup.
    /// @param rollupChainId - The chainId of the destination rollup.
    /// @param rollupRecipient - The recipient of tokens on the rollup.
    /// @param token - The host chain address of the token entering the rollup.
    /// @param amount - The amount of tokens entering the rollup.
    event EnterToken(
        uint256 indexed rollupChainId, address indexed rollupRecipient, address indexed token, uint256 amount
    );

    /// @notice Emitted when the admin withdraws tokens from the contract.
    event Withdrawal(address indexed token, address indexed recipient, uint256 amount);

    /// @notice Emitted when the admin allow/disallow ERC20 Enters for a given token.
    event EnterConfigured(address indexed token, bool indexed canEnter);

    /// @param _defaultRollupChainId - the chainId of the rollup that Ether will be sent to by default
    ///                                when entering the rollup via fallback() or receive() fns.
    constructor(
        uint256 _defaultRollupChainId,
        address _tokenAdmin,
        address[] memory initialEnterTokens,
        address _permit2
    ) UsesPermit2(_permit2) {
        defaultRollupChainId = _defaultRollupChainId;
        tokenAdmin = _tokenAdmin;
        for (uint256 i; i < initialEnterTokens.length; i++) {
            _configureEnter(initialEnterTokens[i], true);
        }
    }

    /// @notice Allows native Ether to enter the rollup by being sent directly to the contract.
    fallback() external payable {
        enter(defaultRollupChainId, msg.sender);
    }

    /// @notice Allows native Ether to enter the rollup by being sent directly to the contract.
    receive() external payable {
        enter(defaultRollupChainId, msg.sender);
    }

    /// @notice Allows native Ether to enter the rollup.
    /// @param rollupChainId - The rollup chain to enter.
    /// @param rollupRecipient - The recipient of the Ether on the rollup.
    /// @custom:emits Enter indicating the amount of Ether to mint on the rollup & its recipient.
    function enter(uint256 rollupChainId, address rollupRecipient) public payable {
        if (msg.value == 0) return;
        emit Enter(rollupChainId, rollupRecipient, msg.value);
    }

    /// @notice Allows native Ether to enter the default rollup.
    /// @dev see `enter` for docs.
    function enter(address rollupRecipient) external payable {
        enter(defaultRollupChainId, rollupRecipient);
    }

    /// @notice Allows ERC20 tokens to enter the rollup.
    /// @param rollupChainId - The rollup chain to enter.
    /// @param rollupRecipient - The recipient of tokens on the rollup.
    /// @param token - The host chain address of the token entering the rollup.
    /// @param amount - The amount of tokens entering the rollup.
    function enterToken(uint256 rollupChainId, address rollupRecipient, address token, uint256 amount)
        public
        nonReentrant
    {
        // transfer tokens to this contract
        IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
        // check and emit
        _enterToken(rollupChainId, rollupRecipient, token, amount);
    }

    /// @notice Allows ERC20 tokens to enter the default rollup.
    /// @dev see `enterToken` for docs.
    function enterToken(address rollupRecipient, address token, uint256 amount) external {
        enterToken(defaultRollupChainId, rollupRecipient, token, amount);
    }

    /// @notice Allows ERC20 tokens to enter the rollup.
    /// @param rollupChainId - The rollup chain to enter.
    /// @param rollupRecipient - The recipient of tokens on the rollup.
    /// @param permit2 - The Permit2 information, including token & amount.
    function enterTokenPermit2(uint256 rollupChainId, address rollupRecipient, PassagePermit2.Permit2 calldata permit2)
        external
        nonReentrant
    {
        // transfer tokens to this contract via permit2
        _permitWitnessTransferFrom(enterWitness(rollupChainId, rollupRecipient), permit2);
        // check and emit
        _enterToken(rollupChainId, rollupRecipient, permit2.permit.permitted.token, permit2.permit.permitted.amount);
    }

    /// @notice Alow/Disallow a given ERC20 token to enter the rollup.
    function configureEnter(address token, bool _canEnter) external {
        if (msg.sender != tokenAdmin) revert OnlyTokenAdmin();
        if (canEnter[token] != _canEnter) _configureEnter(token, _canEnter);
    }

    /// @notice Allows the admin to withdraw ETH or ERC20 tokens from the contract.
    /// @dev Only the admin can call this function.
    function withdraw(address token, address recipient, uint256 amount) external nonReentrant {
        if (msg.sender != tokenAdmin) revert OnlyTokenAdmin();
        if (token == address(0)) {
            payable(recipient).sendValue(amount);
        } else {
            IERC20(token).safeTransfer(recipient, amount);
        }
        emit Withdrawal(token, recipient, amount);
    }

    /// @notice Shared functionality for tokens entering rollup.
    function _enterToken(uint256 rollupChainId, address rollupRecipient, address token, uint256 amount) internal {
        if (amount == 0) return;
        if (!canEnter[token]) revert DisallowedEnter(token);
        emit EnterToken(rollupChainId, rollupRecipient, token, amount);
    }

    /// @notice Helper to configure ERC20 enters on deploy & via admin function
    function _configureEnter(address token, bool _canEnter) internal {
        canEnter[token] = _canEnter;
        emit EnterConfigured(token, _canEnter);
    }
}

// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

import {UsesPermit2} from "../UsesPermit2.sol";
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";

abstract contract PassagePermit2 is UsesPermit2 {
    string constant _ENTER_WITNESS_TYPESTRING =
        "EnterWitness witness)EnterWitness(uint256 rollupChainId,address rollupRecipient)TokenPermissions(address token,uint256 amount)";

    bytes32 constant _ENTER_WITNESS_TYPEHASH = keccak256("EnterWitness(uint256 rollupChainId,address rollupRecipient)");

    string constant _EXIT_WITNESS_TYPESTRING =
        "ExitWitness witness)ExitWitness(address hostRecipient)TokenPermissions(address token,uint256 amount)";

    bytes32 constant _EXIT_WITNESS_TYPEHASH = keccak256("ExitWitness(address hostRecipient)");

    /// @notice Struct to hash Enter witness data into a 32-byte witness field, in an EIP-712 compliant way.
    struct EnterWitness {
        uint256 rollupChainId;
        address rollupRecipient;
    }

    /// @notice Struct to hash Exit witness data into a 32-byte witness field, in an EIP-712 compliant way.
    struct ExitWitness {
        address hostRecipient;
    }

    /// @notice Encode & hash the rollupChainId and rollupRecipient for use as a permit2 witness.
    /// @return _witness - the hashed witness and its typestring.
    function enterWitness(uint256 rollupChainId, address rollupRecipient)
        public
        pure
        returns (Witness memory _witness)
    {
        _witness.witnessHash =
            keccak256(abi.encode(_ENTER_WITNESS_TYPEHASH, EnterWitness(rollupChainId, rollupRecipient)));
        _witness.witnessTypeString = _ENTER_WITNESS_TYPESTRING;
    }

    /// @notice Hash the hostRecipient for use as a permit2 witness.
    /// @return _witness - the hashed witness and its typestring.
    function exitWitness(address hostRecipient) public pure returns (Witness memory _witness) {
        _witness.witnessHash = keccak256(abi.encode(_EXIT_WITNESS_TYPEHASH, ExitWitness(hostRecipient)));
        _witness.witnessTypeString = _EXIT_WITNESS_TYPESTRING;
    }

    /// @notice Transfer tokens using permit2.
    /// @param _witness - the hashed witness and its typestring.
    /// @param permit2 - the Permit2 information.
    function _permitWitnessTransferFrom(Witness memory _witness, Permit2 calldata permit2) internal {
        ISignatureTransfer(permit2Contract).permitWitnessTransferFrom(
            permit2.permit,
            _selfTransferDetails(permit2.permit.permitted.amount),
            permit2.owner,
            _witness.witnessHash,
            _witness.witnessTypeString,
            permit2.signature
        );
    }

    /// @notice Construct TransferDetails transferring a balance to this contract, for passing to permit2.
    /// @dev always transfers the full amount to address(this).
    /// @param amount - the amount to transfer to this contract.
    /// @return transferDetails - the SignatureTransferDetails generated.
    function _selfTransferDetails(uint256 amount)
        internal
        view
        returns (ISignatureTransfer.SignatureTransferDetails memory transferDetails)
    {
        transferDetails.to = address(this);
        transferDetails.requestedAmount = amount;
    }
}

File 3 of 17 : UsesPermit2.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

import {IOrders} from "./orders/IOrders.sol";
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";

abstract contract UsesPermit2 {
    /// @param permit - the permit2 single token transfer details. includes a `deadline` and an unordered `nonce`.
    /// @param signer - the signer of the permit2 info; the owner of the tokens.
    /// @param signature - the signature over the permit + witness.
    struct Permit2 {
        ISignatureTransfer.PermitTransferFrom permit;
        address owner;
        bytes signature;
    }

    /// @param permit - the permit2 batch token transfer details. includes a `deadline` and an unordered `nonce`.
    /// @param signer - the signer of the permit2 info; the owner of the tokens.
    /// @param signature - the signature over the permit + witness.
    struct Permit2Batch {
        ISignatureTransfer.PermitBatchTransferFrom permit;
        address owner;
        bytes signature;
    }

    /// @notice Struct to hold the pre-hashed witness field and the witness type string.
    struct Witness {
        bytes32 witnessHash;
        string witnessTypeString;
    }

    /// @notice The Permit2 contract address.
    address immutable permit2Contract;

    constructor(address _permit2) {
        permit2Contract = _permit2;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 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 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @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 {
        if (!_safeTransfer(token, to, value, true)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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 {
        if (!_safeTransferFrom(token, from, to, value, true)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _safeTransfer(token, to, value, false);
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _safeTransferFrom(token, from, to, value, false);
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @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.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        if (!_safeApprove(token, spender, value, false)) {
            if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));
            if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Oppositely, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity `token.transfer(to, value)` call, 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 to The recipient of the tokens
     * @param value The amount of token to transfer
     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
     */
    function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {
        bytes4 selector = IERC20.transfer.selector;

        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(0x00, selector)
            mstore(0x04, and(to, shr(96, not(0))))
            mstore(0x24, value)
            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
            // if call success and return is true, all is good.
            // otherwise (not success or return is not true), we need to perform further checks
            if iszero(and(success, eq(mload(0x00), 1))) {
                // if the call was a failure and bubble is enabled, bubble the error
                if and(iszero(success), bubble) {
                    returndatacopy(fmp, 0x00, returndatasize())
                    revert(fmp, returndatasize())
                }
                // if the return value is not true, then the call is only successful if:
                // - the token address has code
                // - the returndata is empty
                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
            }
            mstore(0x40, fmp)
        }
    }

    /**
     * @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, 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 from The sender of the tokens
     * @param to The recipient of the tokens
     * @param value The amount of token to transfer
     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
     */
    function _safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value,
        bool bubble
    ) private returns (bool success) {
        bytes4 selector = IERC20.transferFrom.selector;

        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(0x00, selector)
            mstore(0x04, and(from, shr(96, not(0))))
            mstore(0x24, and(to, shr(96, not(0))))
            mstore(0x44, value)
            success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)
            // if call success and return is true, all is good.
            // otherwise (not success or return is not true), we need to perform further checks
            if iszero(and(success, eq(mload(0x00), 1))) {
                // if the call was a failure and bubble is enabled, bubble the error
                if and(iszero(success), bubble) {
                    returndatacopy(fmp, 0x00, returndatasize())
                    revert(fmp, returndatasize())
                }
                // if the return value is not true, then the call is only successful if:
                // - the token address has code
                // - the returndata is empty
                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
            }
            mstore(0x40, fmp)
            mstore(0x60, 0)
        }
    }

    /**
     * @dev Imitates a Solidity `token.approve(spender, value)` call, 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 spender The spender of the tokens
     * @param value The amount of token to transfer
     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
     */
    function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {
        bytes4 selector = IERC20.approve.selector;

        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(0x00, selector)
            mstore(0x04, and(spender, shr(96, not(0))))
            mstore(0x24, value)
            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
            // if call success and return is true, all is good.
            // otherwise (not success or return is not true), we need to perform further checks
            if iszero(and(success, eq(mload(0x00), 1))) {
                // if the call was a failure and bubble is enabled, bubble the error
                if and(iszero(success), bubble) {
                    returndatacopy(fmp, 0x00, returndatasize())
                    revert(fmp, returndatasize())
                }
                // if the return value is not true, then the call is only successful if:
                // - the token address has code
                // - the returndata is empty
                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
            }
            mstore(0x40, fmp)
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/Address.sol)

pragma solidity ^0.8.20;

import {Errors} from "./Errors.sol";
import {LowLevelCall} from "./LowLevelCall.sol";

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert Errors.InsufficientBalance(address(this).balance, amount);
        }
        if (LowLevelCall.callNoReturn(recipient, amount, "")) {
            // call successful, nothing to do
            return;
        } else if (LowLevelCall.returnDataSize() > 0) {
            LowLevelCall.bubbleRevert();
        } else {
            revert Errors.FailedCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {Errors.FailedCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        bool success = LowLevelCall.callNoReturn(target, value, data);
        if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {
            return LowLevelCall.returnData();
        } else if (success) {
            revert AddressEmptyCode(target);
        } else if (LowLevelCall.returnDataSize() > 0) {
            LowLevelCall.bubbleRevert();
        } else {
            revert Errors.FailedCall();
        }
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        bool success = LowLevelCall.staticcallNoReturn(target, data);
        if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {
            return LowLevelCall.returnData();
        } else if (success) {
            revert AddressEmptyCode(target);
        } else if (LowLevelCall.returnDataSize() > 0) {
            LowLevelCall.bubbleRevert();
        } else {
            revert Errors.FailedCall();
        }
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        bool success = LowLevelCall.delegatecallNoReturn(target, data);
        if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {
            return LowLevelCall.returnData();
        } else if (success) {
            revert AddressEmptyCode(target);
        } else if (LowLevelCall.returnDataSize() > 0) {
            LowLevelCall.bubbleRevert();
        } else {
            revert Errors.FailedCall();
        }
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
     * of an unsuccessful call.
     *
     * NOTE: This function is DEPRECATED and may be removed in the next major release.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        // only check if target is a contract if the call was successful and the return data is empty
        // otherwise we already know that it was a contract
        if (success && (returndata.length > 0 || target.code.length > 0)) {
            return returndata;
        } else if (success) {
            revert AddressEmptyCode(target);
        } else if (returndata.length > 0) {
            LowLevelCall.bubbleRevert(returndata);
        } else {
            revert Errors.FailedCall();
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {Errors.FailedCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else if (returndata.length > 0) {
            LowLevelCall.bubbleRevert(returndata);
        } else {
            revert Errors.FailedCall();
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/ReentrancyGuardTransient.sol)

pragma solidity ^0.8.24;

import {TransientSlot} from "./TransientSlot.sol";

/**
 * @dev Variant of {ReentrancyGuard} that uses transient storage.
 *
 * NOTE: This variant only works on networks where EIP-1153 is available.
 *
 * _Available since v5.1._
 *
 * @custom:stateless
 */
abstract contract ReentrancyGuardTransient {
    using TransientSlot for *;

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant REENTRANCY_GUARD_STORAGE =
        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

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

    /**
     * @dev A `view` only version of {nonReentrant}. Use to block view functions
     * from being called, preventing reading from inconsistent contract state.
     *
     * CAUTION: This is a "view" modifier and does not change the reentrancy
     * status. Use it only on view functions. For payable or non-payable functions,
     * use the standard {nonReentrant} modifier instead.
     */
    modifier nonReentrantView() {
        _nonReentrantBeforeView();
        _;
    }

    function _nonReentrantBeforeView() private view {
        if (_reentrancyGuardEntered()) {
            revert ReentrancyGuardReentrantCall();
        }
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false
        _nonReentrantBeforeView();

        // Any calls to nonReentrant after this point will fail
        _reentrancyGuardStorageSlot().asBoolean().tstore(true);
    }

    function _nonReentrantAfter() private {
        _reentrancyGuardStorageSlot().asBoolean().tstore(false);
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _reentrancyGuardStorageSlot().asBoolean().tload();
    }

    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {
        return REENTRANCY_GUARD_STORAGE;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IEIP712} from "./IEIP712.sol";

/// @title SignatureTransfer
/// @notice Handles ERC20 token transfers through signature based actions
/// @dev Requires user's token approval on the Permit2 contract
interface ISignatureTransfer is IEIP712 {
    /// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount
    /// @param maxAmount The maximum amount a spender can request to transfer
    error InvalidAmount(uint256 maxAmount);

    /// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred
    /// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred
    error LengthMismatch();

    /// @notice Emits an event when the owner successfully invalidates an unordered nonce.
    event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);

    /// @notice The token and amount details for a transfer signed in the permit transfer signature
    struct TokenPermissions {
        // ERC20 token address
        address token;
        // the maximum amount that can be spent
        uint256 amount;
    }

    /// @notice The signed permit message for a single token transfer
    struct PermitTransferFrom {
        TokenPermissions permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }

    /// @notice Specifies the recipient address and amount for batched transfers.
    /// @dev Recipients and amounts correspond to the index of the signed token permissions array.
    /// @dev Reverts if the requested amount is greater than the permitted signed amount.
    struct SignatureTransferDetails {
        // recipient address
        address to;
        // spender requested amount
        uint256 requestedAmount;
    }

    /// @notice Used to reconstruct the signed permit message for multiple token transfers
    /// @dev Do not need to pass in spender address as it is required that it is msg.sender
    /// @dev Note that a user still signs over a spender address
    struct PermitBatchTransferFrom {
        // the tokens and corresponding amounts permitted for a transfer
        TokenPermissions[] permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }

    /// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection
    /// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order
    /// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce
    /// @dev It returns a uint256 bitmap
    /// @dev The index, or wordPosition is capped at type(uint248).max
    function nonceBitmap(address, uint256) external view returns (uint256);

    /// @notice Transfers a token using a signed permit message
    /// @dev Reverts if the requested amount is greater than the permitted signed amount
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails The spender's requested transfer details for the permitted token
    /// @param signature The signature to verify
    function permitTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

    /// @notice Transfers a token using a signed permit message
    /// @notice Includes extra data provided by the caller to verify signature over
    /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
    /// @dev Reverts if the requested amount is greater than the permitted signed amount
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails The spender's requested transfer details for the permitted token
    /// @param witness Extra data to include when checking the user signature
    /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
    /// @param signature The signature to verify
    function permitWitnessTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes32 witness,
        string calldata witnessTypeString,
        bytes calldata signature
    ) external;

    /// @notice Transfers multiple tokens using a signed permit message
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails Specifies the recipient and requested amount for the token transfer
    /// @param signature The signature to verify
    function permitTransferFrom(
        PermitBatchTransferFrom memory permit,
        SignatureTransferDetails[] calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

    /// @notice Transfers multiple tokens using a signed permit message
    /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
    /// @notice Includes extra data provided by the caller to verify signature over
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails Specifies the recipient and requested amount for the token transfer
    /// @param witness Extra data to include when checking the user signature
    /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
    /// @param signature The signature to verify
    function permitWitnessTransferFrom(
        PermitBatchTransferFrom memory permit,
        SignatureTransferDetails[] calldata transferDetails,
        address owner,
        bytes32 witness,
        string calldata witnessTypeString,
        bytes calldata signature
    ) external;

    /// @notice Invalidates the bits specified in mask for the bitmap at the word position
    /// @dev The wordPos is maxed at type(uint248).max
    /// @param wordPos A number to index the nonceBitmap at
    /// @param mask A bitmap masked against msg.sender's current bitmap at the word position
    function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;
}

File 9 of 17 : IOrders.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

interface IOrders {
    /// @notice Tokens sent by the swapper as inputs to the order
    /// @dev From ERC-7683
    struct Input {
        /// @dev The address of the ERC20 token on the origin chain
        address token;
        /// @dev The amount of the token to be sent
        uint256 amount;
    }

    /// @notice Tokens that must be receive for a valid order fulfillment
    /// @dev From ERC-7683
    struct Output {
        /// @dev The address of the ERC20 token on the destination chain
        /// @dev address(0) used as a sentinel for the native token
        address token;
        /// @dev The amount of the token to be sent
        uint256 amount;
        /// @dev The address to receive the output tokens
        address recipient;
        /// @dev When emitted on the origin chain, the destination chain for the Output.
        ///      When emitted on the destination chain, the origin chain for the Order containing the Output.
        uint32 chainId;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)

pragma solidity >=0.6.2;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 11 of 17 : Errors.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 *
 * _Available since v5.1._
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();

    /**
     * @dev A necessary precompile is missing.
     */
    error MissingPrecompile(address);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @dev Library of low level call functions that implement different calling strategies to deal with the return data.
 *
 * WARNING: Using this library requires an advanced understanding of Solidity and how the EVM works. It is recommended
 * to use the {Address} library instead.
 */
library LowLevelCall {
    /// @dev Performs a Solidity function call using a low level `call` and ignoring the return data.
    function callNoReturn(address target, bytes memory data) internal returns (bool success) {
        return callNoReturn(target, 0, data);
    }

    /// @dev Same as {callNoReturn}, but allows to specify the value to be sent in the call.
    function callNoReturn(address target, uint256 value, bytes memory data) internal returns (bool success) {
        assembly ("memory-safe") {
            success := call(gas(), target, value, add(data, 0x20), mload(data), 0x00, 0x00)
        }
    }

    /// @dev Performs a Solidity function call using a low level `call` and returns the first 64 bytes of the result
    /// in the scratch space of memory. Useful for functions that return a tuple of single-word values.
    ///
    /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated
    /// and this function doesn't zero it out.
    function callReturn64Bytes(
        address target,
        bytes memory data
    ) internal returns (bool success, bytes32 result1, bytes32 result2) {
        return callReturn64Bytes(target, 0, data);
    }

    /// @dev Same as {callReturnBytes32Pair}, but allows to specify the value to be sent in the call.
    function callReturn64Bytes(
        address target,
        uint256 value,
        bytes memory data
    ) internal returns (bool success, bytes32 result1, bytes32 result2) {
        assembly ("memory-safe") {
            success := call(gas(), target, value, add(data, 0x20), mload(data), 0x00, 0x40)
            result1 := mload(0x00)
            result2 := mload(0x20)
        }
    }

    /// @dev Performs a Solidity function call using a low level `staticcall` and ignoring the return data.
    function staticcallNoReturn(address target, bytes memory data) internal view returns (bool success) {
        assembly ("memory-safe") {
            success := staticcall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x00)
        }
    }

    /// @dev Performs a Solidity function call using a low level `staticcall` and returns the first 64 bytes of the result
    /// in the scratch space of memory. Useful for functions that return a tuple of single-word values.
    ///
    /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated
    /// and this function doesn't zero it out.
    function staticcallReturn64Bytes(
        address target,
        bytes memory data
    ) internal view returns (bool success, bytes32 result1, bytes32 result2) {
        assembly ("memory-safe") {
            success := staticcall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x40)
            result1 := mload(0x00)
            result2 := mload(0x20)
        }
    }

    /// @dev Performs a Solidity function call using a low level `delegatecall` and ignoring the return data.
    function delegatecallNoReturn(address target, bytes memory data) internal returns (bool success) {
        assembly ("memory-safe") {
            success := delegatecall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x00)
        }
    }

    /// @dev Performs a Solidity function call using a low level `delegatecall` and returns the first 64 bytes of the result
    /// in the scratch space of memory. Useful for functions that return a tuple of single-word values.
    ///
    /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated
    /// and this function doesn't zero it out.
    function delegatecallReturn64Bytes(
        address target,
        bytes memory data
    ) internal returns (bool success, bytes32 result1, bytes32 result2) {
        assembly ("memory-safe") {
            success := delegatecall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x40)
            result1 := mload(0x00)
            result2 := mload(0x20)
        }
    }

    /// @dev Returns the size of the return data buffer.
    function returnDataSize() internal pure returns (uint256 size) {
        assembly ("memory-safe") {
            size := returndatasize()
        }
    }

    /// @dev Returns a buffer containing the return data from the last call.
    function returnData() internal pure returns (bytes memory result) {
        assembly ("memory-safe") {
            result := mload(0x40)
            mstore(result, returndatasize())
            returndatacopy(add(result, 0x20), 0x00, returndatasize())
            mstore(0x40, add(result, add(0x20, returndatasize())))
        }
    }

    /// @dev Revert with the return data from the last call.
    function bubbleRevert() internal pure {
        assembly ("memory-safe") {
            let fmp := mload(0x40)
            returndatacopy(fmp, 0x00, returndatasize())
            revert(fmp, returndatasize())
        }
    }

    function bubbleRevert(bytes memory returndata) internal pure {
        assembly ("memory-safe") {
            revert(add(returndata, 0x20), mload(returndata))
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol)
// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.

pragma solidity ^0.8.24;

/**
 * @dev Library for reading and writing value-types to specific transient storage slots.
 *
 * Transient slots are often used to store temporary values that are removed after the current transaction.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 *  * Example reading and writing values using transient storage:
 * ```solidity
 * contract Lock {
 *     using TransientSlot for *;
 *
 *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
 *     bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;
 *
 *     modifier locked() {
 *         require(!_LOCK_SLOT.asBoolean().tload());
 *
 *         _LOCK_SLOT.asBoolean().tstore(true);
 *         _;
 *         _LOCK_SLOT.asBoolean().tstore(false);
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {SlotDerivation}.
 */
library TransientSlot {
    /**
     * @dev UDVT that represents a slot holding an address.
     */
    type AddressSlot is bytes32;

    /**
     * @dev Cast an arbitrary slot to a AddressSlot.
     */
    function asAddress(bytes32 slot) internal pure returns (AddressSlot) {
        return AddressSlot.wrap(slot);
    }

    /**
     * @dev UDVT that represents a slot holding a bool.
     */
    type BooleanSlot is bytes32;

    /**
     * @dev Cast an arbitrary slot to a BooleanSlot.
     */
    function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {
        return BooleanSlot.wrap(slot);
    }

    /**
     * @dev UDVT that represents a slot holding a bytes32.
     */
    type Bytes32Slot is bytes32;

    /**
     * @dev Cast an arbitrary slot to a Bytes32Slot.
     */
    function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {
        return Bytes32Slot.wrap(slot);
    }

    /**
     * @dev UDVT that represents a slot holding a uint256.
     */
    type Uint256Slot is bytes32;

    /**
     * @dev Cast an arbitrary slot to a Uint256Slot.
     */
    function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {
        return Uint256Slot.wrap(slot);
    }

    /**
     * @dev UDVT that represents a slot holding a int256.
     */
    type Int256Slot is bytes32;

    /**
     * @dev Cast an arbitrary slot to a Int256Slot.
     */
    function asInt256(bytes32 slot) internal pure returns (Int256Slot) {
        return Int256Slot.wrap(slot);
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(AddressSlot slot) internal view returns (address value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(AddressSlot slot, address value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(BooleanSlot slot) internal view returns (bool value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(BooleanSlot slot, bool value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(Bytes32Slot slot) internal view returns (bytes32 value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(Bytes32Slot slot, bytes32 value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(Uint256Slot slot) internal view returns (uint256 value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(Uint256Slot slot, uint256 value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(Int256Slot slot) internal view returns (int256 value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(Int256Slot slot, int256 value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IEIP712 {
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 15 of 17 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)

pragma solidity >=0.4.16;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 16 of 17 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)

pragma solidity >=0.4.16;

import {IERC165} from "../utils/introspection/IERC165.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)

pragma solidity >=0.4.16;

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

Settings
{
  "remappings": [
    "@openzeppelin/=lib/stablecoin-evm/node_modules/@openzeppelin/",
    "ds-test/=lib/permit2/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "permit2/=lib/permit2/",
    "safe-smart-account/=lib/safe-smart-account/",
    "simple-erc20/=lib/simple-erc20/src/",
    "solmate/=lib/permit2/lib/solmate/",
    "stablecoin-evm/=lib/stablecoin-evm/"
  ],
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"uint256","name":"_defaultRollupChainId","type":"uint256"},{"internalType":"address","name":"_tokenAdmin","type":"address"},{"internalType":"address[]","name":"initialEnterTokens","type":"address[]"},{"internalType":"address","name":"_permit2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"DisallowedEnter","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"OnlyTokenAdmin","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rollupChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"rollupRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Enter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bool","name":"canEnter","type":"bool"}],"name":"EnterConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rollupChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"rollupRecipient","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EnterToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"canEnter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"_canEnter","type":"bool"}],"name":"configureEnter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultRollupChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rollupRecipient","type":"address"}],"name":"enter","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rollupChainId","type":"uint256"},{"internalType":"address","name":"rollupRecipient","type":"address"}],"name":"enter","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rollupChainId","type":"uint256"},{"internalType":"address","name":"rollupRecipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"enterToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rollupRecipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"enterToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rollupChainId","type":"uint256"},{"internalType":"address","name":"rollupRecipient","type":"address"},{"components":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UsesPermit2.Permit2","name":"permit2","type":"tuple"}],"name":"enterTokenPermit2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rollupChainId","type":"uint256"},{"internalType":"address","name":"rollupRecipient","type":"address"}],"name":"enterWitness","outputs":[{"components":[{"internalType":"bytes32","name":"witnessHash","type":"bytes32"},{"internalType":"string","name":"witnessTypeString","type":"string"}],"internalType":"struct UsesPermit2.Witness","name":"_witness","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"hostRecipient","type":"address"}],"name":"exitWitness","outputs":[{"components":[{"internalType":"bytes32","name":"witnessHash","type":"bytes32"},{"internalType":"string","name":"witnessTypeString","type":"string"}],"internalType":"struct UsesPermit2.Witness","name":"_witness","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"tokenAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e060405234801561000f575f80fd5b50604051611bcf380380611bcf8339818101604052810190610031919061037b565b808073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1681525050508360a081815250508273ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505f5b82518110156100e6576100d98382815181106100c4576100c36103fb565b5b602002602001015160016100f060201b60201c565b80806001019150506100a5565b5050505050610428565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508015158273ffffffffffffffffffffffffffffffffffffffff167f2f8601534249821eb3b2cf9f1d88960ce5b7feb89b9e4a117d2ac7725c56539360405160405180910390a35050565b5f604051905090565b5f80fd5b5f80fd5b5f819050919050565b6101b08161019e565b81146101ba575f80fd5b50565b5f815190506101cb816101a7565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101fa826101d1565b9050919050565b61020a816101f0565b8114610214575f80fd5b50565b5f8151905061022581610201565b92915050565b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6102758261022f565b810181811067ffffffffffffffff821117156102945761029361023f565b5b80604052505050565b5f6102a661018d565b90506102b2828261026c565b919050565b5f67ffffffffffffffff8211156102d1576102d061023f565b5b602082029050602081019050919050565b5f80fd5b5f6102f86102f3846102b7565b61029d565b9050808382526020820190506020840283018581111561031b5761031a6102e2565b5b835b8181101561034457806103308882610217565b84526020840193505060208101905061031d565b5050509392505050565b5f82601f8301126103625761036161022b565b5b81516103728482602086016102e6565b91505092915050565b5f805f806080858703121561039357610392610196565b5b5f6103a0878288016101bd565b94505060206103b187828801610217565b935050604085015167ffffffffffffffff8111156103d2576103d161019a565b5b6103de8782880161034e565b92505060606103ef87828801610217565b91505092959194509250565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60805160a05160c05161175561047a5f395f81816105280152818161060f015261066801525f818160b40152818160e00152818161046901528181610504015261063601525f610a3401526117555ff3fe6080604052600436106100aa575f3560e01c8063b32ed95e11610063578063b32ed95e14610221578063b7e1917c14610249578063d014c01f14610273578063d9caed121461028f578063ea3b9ba1146102b7578063eba1f981146102d3576100db565b806322ac3885146101075780633930e3911461012f578063416ef5a81461016b5780634f8b4a3c14610193578063942c39db146101cf57806395577b72146101f7576100db565b366100db576100d97f00000000000000000000000000000000000000000000000000000000000000003361030f565b005b6101057f00000000000000000000000000000000000000000000000000000000000000003361030f565b005b348015610112575f80fd5b5061012d60048036038101906101289190610f72565b61036b565b005b34801561013a575f80fd5b5061015560048036038101906101509190610fd6565b6103ba565b60405161016291906110d6565b60405180910390f35b348015610176575f80fd5b50610191600480360381019061018c91906110f6565b610464565b005b34801561019e575f80fd5b506101b960048036038101906101b49190611146565b610495565b6040516101c6919061118b565b60405180910390f35b3480156101da575f80fd5b506101f560048036038101906101f091906111c6565b6104b1565b005b348015610202575f80fd5b5061020b610502565b6040516102189190611241565b60405180910390f35b34801561022c575f80fd5b5061024760048036038101906102429190611284565b610526565b005b348015610254575f80fd5b5061025d61060d565b60405161026a91906112d1565b60405180910390f35b61028d60048036038101906102889190611146565b610631565b005b34801561029a575f80fd5b506102b560048036038101906102b091906110f6565b61065e565b005b6102d160048036038101906102cc9190610fd6565b61030f565b005b3480156102de575f80fd5b506102f960048036038101906102f49190611146565b6107ea565b60405161030691906110d6565b60405180910390f35b5f340315610367578073ffffffffffffffffffffffffffffffffffffffff16827f5f67e0a44fbb8ec0f3794c6687c657244a50a7da2411d14707aa219d86b854923460405161035e9190611241565b60405180910390a35b5050565b61037361088d565b6103a03330838573ffffffffffffffffffffffffffffffffffffffff166108ba909392919063ffffffff16565b6103ac8484848461090f565b6103b4610a0e565b50505050565b6103c2610e93565b7fc5d03356b54a64d088070694ab907941e70a5ea4ae772ff6df7f162d054037b660405180604001604052808581526020018473ffffffffffffffffffffffffffffffffffffffff1681525060405160200161041f929190611344565b60405160208183030381529060405280519060200120815f0181815250506040518060a00160405280607e815260200161163e607e9139816020018190525092915050565b6104907f000000000000000000000000000000000000000000000000000000000000000084848461036b565b505050565b5f602052805f5260405f205f915054906101000a900460ff1681565b6104b961088d565b6104cc6104c684846103ba565b82610a32565b6104f58383835f015f015f0160208101906104e79190611146565b845f015f016020013561090f565b6104fd610a0e565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105ab576040517f21dba17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015155f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16151514610609576106088282610b01565b5b5050565b7f000000000000000000000000000000000000000000000000000000000000000081565b61065b7f00000000000000000000000000000000000000000000000000000000000000008261030f565b50565b61066661088d565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106eb576040517f21dba17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361074c57610747818373ffffffffffffffffffffffffffffffffffffffff16610b9e90919063ffffffff16565b610778565b61077782828573ffffffffffffffffffffffffffffffffffffffff16610c559092919063ffffffff16565b5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398836040516107d59190611241565b60405180910390a36107e5610a0e565b505050565b6107f2610e93565b7fa91a2bac0243280e19cfd0a3ae9d7639a15fa41d49eab3e0bf320c8485cc66a960405180602001604052808473ffffffffffffffffffffffffffffffffffffffff16815250604051602001610849929190611385565b60405160208183030381529060405280519060200120815f0181815250506040518060a00160405280606481526020016116bc606491398160200181905250919050565b610895610ca8565b6108b860016108aa6108a5610ce9565b610d12565b610d1b90919063ffffffff16565b565b6108c8848484846001610d22565b61090957836040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161090091906112d1565b60405180910390fd5b50505050565b5f810315610a08575f808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff166109a157816040517f087fe76b00000000000000000000000000000000000000000000000000000000815260040161099891906112d1565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f918d96675770fc73e96feacdd04b31ed125e0e5e0223938cd0043a42228a49e4846040516109ff9190611241565b60405180910390a45b50505050565b610a305f610a22610a1d610ce9565b610d12565b610d1b90919063ffffffff16565b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663137c29fe825f01610a82845f015f0160200135610d93565b846080016020810190610a959190611146565b865f01518760200151878060a00190610aae91906113b8565b6040518863ffffffff1660e01b8152600401610ad097969594939291906115a4565b5f604051808303815f87803b158015610ae7575f80fd5b505af1158015610af9573d5f803e3d5ffd5b505050505050565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508015158273ffffffffffffffffffffffffffffffffffffffff167f2f8601534249821eb3b2cf9f1d88960ce5b7feb89b9e4a117d2ac7725c56539360405160405180910390a35050565b80471015610be55747816040517fcf479181000000000000000000000000000000000000000000000000000000008152600401610bdc929190611616565b60405180910390fd5b610bfe828260405180602001604052805f815250610de1565b610c51575f610c0b610df7565b1115610c1e57610c19610dfe565b610c50565b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5050565b610c628383836001610e09565b610ca357826040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401610c9a91906112d1565b60405180910390fd5b505050565b610cb0610e6b565b15610ce7576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005f1b905090565b5f819050919050565b80825d5050565b5f806323b872dd60e01b9050604051815f525f1960601c87166004525f1960601c86166024528460445260205f60645f808c5af1925060015f51148316610d80578383151615610d74573d5f823e3d81fd5b5f883b113d1516831692505b806040525f606052505095945050505050565b610d9b610eaf565b30815f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081816020018181525050919050565b5f805f83516020850186885af190509392505050565b5f3d905090565b6040513d5f823e3d81fd5b5f8063a9059cbb60e01b9050604051815f525f1960601c86166004528460245260205f60445f808b5af1925060015f51148316610e5d578383151615610e51573d5f823e3d81fd5b5f873b113d1516831692505b806040525050949350505050565b5f610e84610e7f610e7a610ce9565b610d12565b610e89565b905090565b5f815c9050919050565b60405180604001604052805f8019168152602001606081525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525090565b5f80fd5b5f80fd5b5f819050919050565b610ef781610ee5565b8114610f01575f80fd5b50565b5f81359050610f1281610eee565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610f4182610f18565b9050919050565b610f5181610f37565b8114610f5b575f80fd5b50565b5f81359050610f6c81610f48565b92915050565b5f805f8060808587031215610f8a57610f89610edd565b5b5f610f9787828801610f04565b9450506020610fa887828801610f5e565b9350506040610fb987828801610f5e565b9250506060610fca87828801610f04565b91505092959194509250565b5f8060408385031215610fec57610feb610edd565b5b5f610ff985828601610f04565b925050602061100a85828601610f5e565b9150509250929050565b5f819050919050565b61102681611014565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61106e8261102c565b6110788185611036565b9350611088818560208601611046565b61109181611054565b840191505092915050565b5f604083015f8301516110b15f86018261101d565b50602083015184820360208601526110c98282611064565b9150508091505092915050565b5f6020820190508181035f8301526110ee818461109c565b905092915050565b5f805f6060848603121561110d5761110c610edd565b5b5f61111a86828701610f5e565b935050602061112b86828701610f5e565b925050604061113c86828701610f04565b9150509250925092565b5f6020828403121561115b5761115a610edd565b5b5f61116884828501610f5e565b91505092915050565b5f8115159050919050565b61118581611171565b82525050565b5f60208201905061119e5f83018461117c565b92915050565b5f80fd5b5f60c082840312156111bd576111bc6111a4565b5b81905092915050565b5f805f606084860312156111dd576111dc610edd565b5b5f6111ea86828701610f04565b93505060206111fb86828701610f5e565b925050604084013567ffffffffffffffff81111561121c5761121b610ee1565b5b611228868287016111a8565b9150509250925092565b61123b81610ee5565b82525050565b5f6020820190506112545f830184611232565b92915050565b61126381611171565b811461126d575f80fd5b50565b5f8135905061127e8161125a565b92915050565b5f806040838503121561129a57611299610edd565b5b5f6112a785828601610f5e565b92505060206112b885828601611270565b9150509250929050565b6112cb81610f37565b82525050565b5f6020820190506112e45f8301846112c2565b92915050565b6112f381611014565b82525050565b61130281610ee5565b82525050565b61131181610f37565b82525050565b604082015f82015161132b5f8501826112f9565b50602082015161133e6020850182611308565b50505050565b5f6060820190506113575f8301856112ea565b6113646020830184611317565b9392505050565b602082015f82015161137f5f850182611308565b50505050565b5f6040820190506113985f8301856112ea565b6113a5602083018461136b565b9392505050565b5f80fd5b5f80fd5b5f80fd5b5f80833560016020038436030381126113d4576113d36113ac565b5b80840192508235915067ffffffffffffffff8211156113f6576113f56113b0565b5b602083019250600182023603831315611412576114116113b4565b5b509250929050565b5f82905092915050565b5f6114326020840184610f5e565b905092915050565b5f6114486020840184610f04565b905092915050565b604082016114605f830183611424565b61146c5f850182611308565b5061147a602083018361143a565b61148760208501826112f9565b50505050565b6080820161149d5f83018361141a565b6114a95f850182611450565b506114b7604083018361143a565b6114c460408501826112f9565b506114d2606083018361143a565b6114df60608501826112f9565b50505050565b604082015f8201516114f95f850182611308565b50602082015161150c60208501826112f9565b50505050565b5f82825260208201905092915050565b5f61152c8261102c565b6115368185611512565b9350611546818560208601611046565b61154f81611054565b840191505092915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f611583838561155a565b935061159083858461156a565b61159983611054565b840190509392505050565b5f610140820190506115b85f83018a61148d565b6115c560808301896114e5565b6115d260c08301886112c2565b6115df60e08301876112ea565b8181036101008301526115f28186611522565b9050818103610120830152611608818486611578565b905098975050505050505050565b5f6040820190506116295f830185611232565b6116366020830184611232565b939250505056fe456e7465725769746e657373207769746e65737329456e7465725769746e6573732875696e7432353620726f6c6c7570436861696e49642c6164647265737320726f6c6c7570526563697069656e7429546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75696e7432353620616d6f756e7429457869745769746e657373207769746e65737329457869745769746e657373286164647265737320686f7374526563697069656e7429546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75696e7432353620616d6f756e7429a2646970667358221220a157bcb9385794d213fbb8872b67d58e9b0bc081338a211cce080e2c2c2f80d864736f6c634300081a00330000000000000000000000000000000000000000000000000000000000000207000000000000000000000000fa963e3d8dfd6817aaf70140c1fbaea094090fa00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba300000000000000000000000000000000000000000000000000000000000000040000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7

Deployed Bytecode

0x6080604052600436106100aa575f3560e01c8063b32ed95e11610063578063b32ed95e14610221578063b7e1917c14610249578063d014c01f14610273578063d9caed121461028f578063ea3b9ba1146102b7578063eba1f981146102d3576100db565b806322ac3885146101075780633930e3911461012f578063416ef5a81461016b5780634f8b4a3c14610193578063942c39db146101cf57806395577b72146101f7576100db565b366100db576100d97f00000000000000000000000000000000000000000000000000000000000002073361030f565b005b6101057f00000000000000000000000000000000000000000000000000000000000002073361030f565b005b348015610112575f80fd5b5061012d60048036038101906101289190610f72565b61036b565b005b34801561013a575f80fd5b5061015560048036038101906101509190610fd6565b6103ba565b60405161016291906110d6565b60405180910390f35b348015610176575f80fd5b50610191600480360381019061018c91906110f6565b610464565b005b34801561019e575f80fd5b506101b960048036038101906101b49190611146565b610495565b6040516101c6919061118b565b60405180910390f35b3480156101da575f80fd5b506101f560048036038101906101f091906111c6565b6104b1565b005b348015610202575f80fd5b5061020b610502565b6040516102189190611241565b60405180910390f35b34801561022c575f80fd5b5061024760048036038101906102429190611284565b610526565b005b348015610254575f80fd5b5061025d61060d565b60405161026a91906112d1565b60405180910390f35b61028d60048036038101906102889190611146565b610631565b005b34801561029a575f80fd5b506102b560048036038101906102b091906110f6565b61065e565b005b6102d160048036038101906102cc9190610fd6565b61030f565b005b3480156102de575f80fd5b506102f960048036038101906102f49190611146565b6107ea565b60405161030691906110d6565b60405180910390f35b5f340315610367578073ffffffffffffffffffffffffffffffffffffffff16827f5f67e0a44fbb8ec0f3794c6687c657244a50a7da2411d14707aa219d86b854923460405161035e9190611241565b60405180910390a35b5050565b61037361088d565b6103a03330838573ffffffffffffffffffffffffffffffffffffffff166108ba909392919063ffffffff16565b6103ac8484848461090f565b6103b4610a0e565b50505050565b6103c2610e93565b7fc5d03356b54a64d088070694ab907941e70a5ea4ae772ff6df7f162d054037b660405180604001604052808581526020018473ffffffffffffffffffffffffffffffffffffffff1681525060405160200161041f929190611344565b60405160208183030381529060405280519060200120815f0181815250506040518060a00160405280607e815260200161163e607e9139816020018190525092915050565b6104907f000000000000000000000000000000000000000000000000000000000000020784848461036b565b505050565b5f602052805f5260405f205f915054906101000a900460ff1681565b6104b961088d565b6104cc6104c684846103ba565b82610a32565b6104f58383835f015f015f0160208101906104e79190611146565b845f015f016020013561090f565b6104fd610a0e565b505050565b7f000000000000000000000000000000000000000000000000000000000000020781565b7f000000000000000000000000fa963e3d8dfd6817aaf70140c1fbaea094090fa073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105ab576040517f21dba17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015155f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16151514610609576106088282610b01565b5b5050565b7f000000000000000000000000fa963e3d8dfd6817aaf70140c1fbaea094090fa081565b61065b7f00000000000000000000000000000000000000000000000000000000000002078261030f565b50565b61066661088d565b7f000000000000000000000000fa963e3d8dfd6817aaf70140c1fbaea094090fa073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106eb576040517f21dba17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361074c57610747818373ffffffffffffffffffffffffffffffffffffffff16610b9e90919063ffffffff16565b610778565b61077782828573ffffffffffffffffffffffffffffffffffffffff16610c559092919063ffffffff16565b5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398836040516107d59190611241565b60405180910390a36107e5610a0e565b505050565b6107f2610e93565b7fa91a2bac0243280e19cfd0a3ae9d7639a15fa41d49eab3e0bf320c8485cc66a960405180602001604052808473ffffffffffffffffffffffffffffffffffffffff16815250604051602001610849929190611385565b60405160208183030381529060405280519060200120815f0181815250506040518060a00160405280606481526020016116bc606491398160200181905250919050565b610895610ca8565b6108b860016108aa6108a5610ce9565b610d12565b610d1b90919063ffffffff16565b565b6108c8848484846001610d22565b61090957836040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161090091906112d1565b60405180910390fd5b50505050565b5f810315610a08575f808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff166109a157816040517f087fe76b00000000000000000000000000000000000000000000000000000000815260040161099891906112d1565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f918d96675770fc73e96feacdd04b31ed125e0e5e0223938cd0043a42228a49e4846040516109ff9190611241565b60405180910390a45b50505050565b610a305f610a22610a1d610ce9565b610d12565b610d1b90919063ffffffff16565b565b7f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba373ffffffffffffffffffffffffffffffffffffffff1663137c29fe825f01610a82845f015f0160200135610d93565b846080016020810190610a959190611146565b865f01518760200151878060a00190610aae91906113b8565b6040518863ffffffff1660e01b8152600401610ad097969594939291906115a4565b5f604051808303815f87803b158015610ae7575f80fd5b505af1158015610af9573d5f803e3d5ffd5b505050505050565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508015158273ffffffffffffffffffffffffffffffffffffffff167f2f8601534249821eb3b2cf9f1d88960ce5b7feb89b9e4a117d2ac7725c56539360405160405180910390a35050565b80471015610be55747816040517fcf479181000000000000000000000000000000000000000000000000000000008152600401610bdc929190611616565b60405180910390fd5b610bfe828260405180602001604052805f815250610de1565b610c51575f610c0b610df7565b1115610c1e57610c19610dfe565b610c50565b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5050565b610c628383836001610e09565b610ca357826040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401610c9a91906112d1565b60405180910390fd5b505050565b610cb0610e6b565b15610ce7576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005f1b905090565b5f819050919050565b80825d5050565b5f806323b872dd60e01b9050604051815f525f1960601c87166004525f1960601c86166024528460445260205f60645f808c5af1925060015f51148316610d80578383151615610d74573d5f823e3d81fd5b5f883b113d1516831692505b806040525f606052505095945050505050565b610d9b610eaf565b30815f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081816020018181525050919050565b5f805f83516020850186885af190509392505050565b5f3d905090565b6040513d5f823e3d81fd5b5f8063a9059cbb60e01b9050604051815f525f1960601c86166004528460245260205f60445f808b5af1925060015f51148316610e5d578383151615610e51573d5f823e3d81fd5b5f873b113d1516831692505b806040525050949350505050565b5f610e84610e7f610e7a610ce9565b610d12565b610e89565b905090565b5f815c9050919050565b60405180604001604052805f8019168152602001606081525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525090565b5f80fd5b5f80fd5b5f819050919050565b610ef781610ee5565b8114610f01575f80fd5b50565b5f81359050610f1281610eee565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610f4182610f18565b9050919050565b610f5181610f37565b8114610f5b575f80fd5b50565b5f81359050610f6c81610f48565b92915050565b5f805f8060808587031215610f8a57610f89610edd565b5b5f610f9787828801610f04565b9450506020610fa887828801610f5e565b9350506040610fb987828801610f5e565b9250506060610fca87828801610f04565b91505092959194509250565b5f8060408385031215610fec57610feb610edd565b5b5f610ff985828601610f04565b925050602061100a85828601610f5e565b9150509250929050565b5f819050919050565b61102681611014565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61106e8261102c565b6110788185611036565b9350611088818560208601611046565b61109181611054565b840191505092915050565b5f604083015f8301516110b15f86018261101d565b50602083015184820360208601526110c98282611064565b9150508091505092915050565b5f6020820190508181035f8301526110ee818461109c565b905092915050565b5f805f6060848603121561110d5761110c610edd565b5b5f61111a86828701610f5e565b935050602061112b86828701610f5e565b925050604061113c86828701610f04565b9150509250925092565b5f6020828403121561115b5761115a610edd565b5b5f61116884828501610f5e565b91505092915050565b5f8115159050919050565b61118581611171565b82525050565b5f60208201905061119e5f83018461117c565b92915050565b5f80fd5b5f60c082840312156111bd576111bc6111a4565b5b81905092915050565b5f805f606084860312156111dd576111dc610edd565b5b5f6111ea86828701610f04565b93505060206111fb86828701610f5e565b925050604084013567ffffffffffffffff81111561121c5761121b610ee1565b5b611228868287016111a8565b9150509250925092565b61123b81610ee5565b82525050565b5f6020820190506112545f830184611232565b92915050565b61126381611171565b811461126d575f80fd5b50565b5f8135905061127e8161125a565b92915050565b5f806040838503121561129a57611299610edd565b5b5f6112a785828601610f5e565b92505060206112b885828601611270565b9150509250929050565b6112cb81610f37565b82525050565b5f6020820190506112e45f8301846112c2565b92915050565b6112f381611014565b82525050565b61130281610ee5565b82525050565b61131181610f37565b82525050565b604082015f82015161132b5f8501826112f9565b50602082015161133e6020850182611308565b50505050565b5f6060820190506113575f8301856112ea565b6113646020830184611317565b9392505050565b602082015f82015161137f5f850182611308565b50505050565b5f6040820190506113985f8301856112ea565b6113a5602083018461136b565b9392505050565b5f80fd5b5f80fd5b5f80fd5b5f80833560016020038436030381126113d4576113d36113ac565b5b80840192508235915067ffffffffffffffff8211156113f6576113f56113b0565b5b602083019250600182023603831315611412576114116113b4565b5b509250929050565b5f82905092915050565b5f6114326020840184610f5e565b905092915050565b5f6114486020840184610f04565b905092915050565b604082016114605f830183611424565b61146c5f850182611308565b5061147a602083018361143a565b61148760208501826112f9565b50505050565b6080820161149d5f83018361141a565b6114a95f850182611450565b506114b7604083018361143a565b6114c460408501826112f9565b506114d2606083018361143a565b6114df60608501826112f9565b50505050565b604082015f8201516114f95f850182611308565b50602082015161150c60208501826112f9565b50505050565b5f82825260208201905092915050565b5f61152c8261102c565b6115368185611512565b9350611546818560208601611046565b61154f81611054565b840191505092915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f611583838561155a565b935061159083858461156a565b61159983611054565b840190509392505050565b5f610140820190506115b85f83018a61148d565b6115c560808301896114e5565b6115d260c08301886112c2565b6115df60e08301876112ea565b8181036101008301526115f28186611522565b9050818103610120830152611608818486611578565b905098975050505050505050565b5f6040820190506116295f830185611232565b6116366020830184611232565b939250505056fe456e7465725769746e657373207769746e65737329456e7465725769746e6573732875696e7432353620726f6c6c7570436861696e49642c6164647265737320726f6c6c7570526563697069656e7429546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75696e7432353620616d6f756e7429457869745769746e657373207769746e65737329457869745769746e657373286164647265737320686f7374526563697069656e7429546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75696e7432353620616d6f756e7429a2646970667358221220a157bcb9385794d213fbb8872b67d58e9b0bc081338a211cce080e2c2c2f80d864736f6c634300081a0033

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

0000000000000000000000000000000000000000000000000000000000000207000000000000000000000000fa963e3d8dfd6817aaf70140c1fbaea094090fa00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba300000000000000000000000000000000000000000000000000000000000000040000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7

-----Decoded View---------------
Arg [0] : _defaultRollupChainId (uint256): 519
Arg [1] : _tokenAdmin (address): 0xfa963E3D8dfD6817aAF70140C1fbAEA094090Fa0
Arg [2] : initialEnterTokens (address[]): 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599,0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48,0xdAC17F958D2ee523a2206206994597C13D831ec7
Arg [3] : _permit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000207
Arg [1] : 000000000000000000000000fa963e3d8dfd6817aaf70140c1fbaea094090fa0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [5] : 0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599
Arg [6] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [7] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [8] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7


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

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