false
true

Contract Address Details

0x08821E390c3a8a4f36e8c1fdF32D1c28795141A3

Contract Name
L2CrossTrade
Creator
0xf0b595ā€“6035ea at 0xf5438dā€“9f5645
Balance
0 ETH
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
7262
Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0x56e7b6489e8012172766f348c6be0f351b854880.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
Contract name:
L2CrossTrade




Optimization enabled
true
Compiler version
v0.8.24+commit.e11b9ed9




Optimization runs
100000000
Verified at
2024-08-19T10:17:14.796762Z

contracts/L2/L2CrossTrade.sol

Sol2uml
new
// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.24;

import "../libraries/SafeERC20.sol";
import "../proxy/ProxyStorage.sol";

import { AccessibleCommon } from "../common/AccessibleCommon.sol";
import { L2CrossTradeStorage } from "./L2CrossTradeStorage.sol";
import { IOptimismMintableERC20, ILegacyMintableERC20 } from "../interfaces/IOptimismMintableERC20.sol";
import { IL2CrossDomainMessenger } from "../interfaces/IL2CrossDomainMessenger.sol";
import { ReentrancyGuard } from "../utils/ReentrancyGuard.sol";

// import "hardhat/console.sol";

contract L2CrossTrade is ProxyStorage, AccessibleCommon, L2CrossTradeStorage, ReentrancyGuard {

    using SafeERC20 for IERC20;

    event RequestCT(
        address _l1token,
        address _l2token,
        address _requester,
        uint256 _totalAmount,
        uint256 _ctAmount,
        uint256 indexed _saleCount,
        uint256 _l2chainId,
        bytes32 _hashValue
    );

    event NonRequestCT(
        address _l1token,
        address _l2token,
        address _requester,
        uint256 _totalAmount,
        uint256 _ctAmount,
        uint256 indexed _saleCount,
        uint256 _l2chainId,
        bytes32 _hashValue
    );

    event ProviderClaimCT(
        address _l1token,
        address _l2token,
        address _requester,
        address _provider,
        uint256 _totalAmount,
        uint256 _ctAmount,
        uint256 indexed _saleCount,
        uint256 _l2chainId,
        bytes32 _hash
    );
    
    event CancelCT(
        address _requester,
        uint256 _totalAmount,
        uint256 indexed _saleCount,
        uint256 _l2chainId,
        bytes32 _hash
    );

    // event EditCT(
    //     address _requester,
    //     uint256 _ctAmount,
    //     uint256 indexed _saleCount
    // );

    //=======modifier========

    modifier onlyEOA() {
        require(msg.sender == tx.origin, "L2FW: function can only be called from an EOA");
        _;
    }

    modifier checkL1(uint256 _chainId) {
        require(
            msg.sender == address(crossDomainMessenger) && IL2CrossDomainMessenger(crossDomainMessenger).xDomainMessageSender() == chainData[_chainId].l1CrossTradeContract, 
            "only call l1FastWithdraw"
        );
        _;
    }

    modifier providerCheck(uint256 _saleCount) {
        require(dealData[_saleCount].provider == address(0), "already sold");
        _;
    }

    modifier nonZero(uint256 _amount) {
        require(_amount > 0 , "input amount need nonZero");
        _;
    }

    // modifier nonZeroAddr(address _addr) {
    //     require(_addr != address(0) , "nonZeroAddr");
    //     _;
    // }

    //=======external========

    /// @notice Register L1token and L2token and use them in requestRegisteredToken
    /// @param _l1token l1token Address
    /// @param _l2token l2token Address
    /// @param _l1chainId chainId of l1token
    function registerToken(
        address _l1token,
        address _l2token,
        uint256 _l1chainId
    )
        external
        onlyOwner
    {
        require(registerCheck[_l1chainId][_l1token][_l2token] == false, "already registerToken");
        registerCheck[_l1chainId][_l1token][_l2token] = true;
    }
    
    /// @notice Function to delete registered token
    /// @param _l1token l1token Address
    /// @param _l2token l2token Address
    /// @param _l1chainId chainId of l1token
    function deleteToken(
        address _l1token,
        address _l2token,
        uint256 _l1chainId
    )
        external
        onlyOwner
    {
        require(registerCheck[_l1chainId][_l1token][_l2token] != false, "already deleteToken");
        registerCheck[_l1chainId][_l1token][_l2token] = false;
    }

    /// @notice Token transaction request registered in register
    /// @param _l1token l1token Address
    /// @param _l2token l2token Address
    /// @param _totalAmount Amount provided to L2
    /// @param _ctAmount Amount to be received from L1
    /// @param _l1chainId chainId of l1token
    function requestRegisteredToken(
        address _l1token,
        address _l2token,
        uint256 _totalAmount,
        uint256 _ctAmount,
        uint256 _l1chainId
    )
        external
        payable
        onlyEOA
        nonZero(_totalAmount)
        nonZero(_ctAmount)
        nonReentrant
    {
        require(registerCheck[_l1chainId][_l1token][_l2token] == true, "not register token");
        require(_totalAmount >= _ctAmount, "The totalAmount value must be greater than ctAmount");
        
        unchecked {
            ++saleCount;
        }

        bytes32 hashValue = _request(
            _l1token,
            _l2token,
            _totalAmount,
            _ctAmount,
            saleCount,
            _l1chainId
        );

        uint256 chainId = _getChainID();

        emit RequestCT(
            _l1token,
            _l2token,
            msg.sender,
            _totalAmount,
            _ctAmount,
            saleCount,
            chainId,
            hashValue
        );
    }

    /// @notice Token transaction request not registered in register
    /// @param _l1token l1token Address
    /// @param _l2token l2token Address
    /// @param _totalAmount Amount provided to L2
    /// @param _ctAmount Amount to be received from L1
    /// @param _l1chainId chainId of l1token
    function requestNonRegisteredToken(
        address _l1token,
        address _l2token,
        uint256 _totalAmount,
        uint256 _ctAmount,
        uint256 _l1chainId
    )
        external
        payable
        onlyEOA
        nonZero(_totalAmount)
        nonZero(_ctAmount)
        nonReentrant
    {        
        unchecked {
            ++saleCount;
        }

        bytes32 hashValue = _request(
            _l1token,
            _l2token,
            _totalAmount,
            _ctAmount,
            saleCount,
            _l1chainId
        );

        uint256 chainId = _getChainID();

        emit NonRequestCT(
            _l1token,
            _l2token,
            msg.sender,
            _totalAmount,
            _ctAmount,
            saleCount,
            chainId,
            hashValue
        );
    }
    
    /// @notice When providing a function called from L1, the amount is given to the provider.
    /// @param _from provider Address
    /// @param _ctAmount Amount paid by L1
    /// @param _saleCount Number generated upon request
    /// @param _chainId chainId of l1token
    /// @param _hash Hash value generated upon request
    function claimCT(
        address _from,
        uint256 _ctAmount,
        uint256 _saleCount,
        uint256 _chainId,
        bytes32 _hash
    )
        external
        nonReentrant
        checkL1(_chainId)
        providerCheck(_saleCount)
    {
        require(dealData[_saleCount].hashValue == _hash, "Hash values do not match");

        uint256 ctAmount = _ctAmount;
        if(_ctAmount == 0) {
            ctAmount = dealData[_saleCount].ctAmount;
        } 

        dealData[_saleCount].provider = _from;
        address l2token = dealData[_saleCount].l2token;
        uint256 totalAmount = dealData[_saleCount].totalAmount;

        if(l2token == legacyERC20ETH) {
            (bool sent, ) = payable(_from).call{value: totalAmount}("");
            require(sent, "claim fail");
        } else {
            IERC20(l2token).safeTransfer(_from,totalAmount);
        }

        uint256 chainId = _getChainID();

        emit ProviderClaimCT(
            dealData[_saleCount].l1token,
            l2token,
            dealData[_saleCount].requester,
            _from,
            totalAmount,
            ctAmount,
            _saleCount,
            chainId,
            _hash
        );
    }
    
    /// @notice When canceling a function called from L1, the amount is given to the requester.
    /// @param _msgSender Address where cancellation was requested
    /// @param _salecount Number generated upon request
    /// @param _chainId chainId of l1token
    /// @param _hash Hash value generated upon request
    function cancelCT(
        address _msgSender,
        uint256 _salecount,
        uint256 _chainId,
        bytes32 _hash
    )
        external
        nonReentrant
        checkL1(_chainId)
        providerCheck(_salecount)
    {
        require(dealData[_salecount].requester == _msgSender, "your not seller");
        require(dealData[_salecount].hashValue == _hash, "Hash values do not match");

        dealData[_salecount].provider = _msgSender;
        uint256 totalAmount = dealData[_salecount].totalAmount;
        
        if (dealData[_salecount].l2token == legacyERC20ETH) {
            (bool sent, ) = payable(_msgSender).call{value: totalAmount}("");
            require(sent, "cancel refund fail");
        } else {
            IERC20(dealData[_salecount].l2token).safeTransfer(_msgSender,totalAmount);
        }

        uint256 chainId = _getChainID();

        emit CancelCT(
            _msgSender, 
            totalAmount, 
            _salecount,
            chainId,
            _hash
        );
    }

    function claimOwnerCT(
        address _from,
        uint256 _ctAmount,
        uint256 _saleCount,
        uint256 _chainId,
        bytes32 _hash
    )
        external
        onlyOwner
        nonReentrant
        providerCheck(_saleCount)
    {
        require(dealData[_saleCount].hashValue == _hash, "Hash values do not match");

        uint256 ctAmount = _ctAmount;
        if(_ctAmount == 0) {
            ctAmount = dealData[_saleCount].ctAmount;
        } 

        dealData[_saleCount].provider = _from;
        address l2token = dealData[_saleCount].l2token;
        uint256 totalAmount = dealData[_saleCount].totalAmount;

        if(l2token == legacyERC20ETH) {
            (bool sent, ) = payable(_from).call{value: totalAmount}("");
            require(sent, "claim fail");
        } else {
            IERC20(l2token).safeTransfer(_from,totalAmount);
        }

        uint256 chainId = _getChainID();

        emit ProviderClaimCT(
            dealData[_saleCount].l1token,
            l2token,
            dealData[_saleCount].requester,
            _from,
            totalAmount,
            ctAmount,
            _saleCount,
            chainId,
            _hash
        );
    }

    function cancelOwnerCT(
        address _msgSender,
        uint256 _salecount,
        uint256 _chainId,
        bytes32 _hash
    )
        external
        onlyOwner
        nonReentrant
        providerCheck(_salecount)
    {
        require(dealData[_salecount].requester == _msgSender, "your not seller");
        require(dealData[_salecount].hashValue == _hash, "Hash values do not match");

        dealData[_salecount].provider = _msgSender;
        uint256 totalAmount = dealData[_salecount].totalAmount;
        
        if (dealData[_salecount].l2token == legacyERC20ETH) {
            (bool sent, ) = payable(_msgSender).call{value: totalAmount}("");
            require(sent, "cancel refund fail");
        } else {
            IERC20(dealData[_salecount].l2token).safeTransfer(_msgSender,totalAmount);
        }

        uint256 chainId = _getChainID();

        emit CancelCT(
            _msgSender, 
            totalAmount, 
            _salecount,
            chainId,
            _hash
        );
    }

    function checkModify(
        address _crossDomainMessenger,
        address _xDomainMessageSender,
        uint256 _chainId
    )
        external
        view
        returns (uint256 modify)
    {
        if (_crossDomainMessenger != address(crossDomainMessenger)) {
            return modify = 1;
        } else if (_xDomainMessageSender != chainData[_chainId].l1CrossTradeContract) {
            return modify = 2;
        }
        return modify = 3;
    }


    /// @notice Function that calculates hash value in L2CrossTradeContract
    /// @param _l1token l1token Address
    /// @param _l2token l2token Address
    /// @param _requestor requester's address
    /// @param _totalAmount Amount provided to L2
    /// @param _ctAmount Amount provided to L2
    /// @param _saleCount Number generated upon request
    /// @param _startChainId The chainId where this contract was deployed
    /// @param _endChainId Destination chainID
    function getHash(
        address _l1token,
        address _l2token,
        address _requestor,
        uint256 _totalAmount,
        uint256 _ctAmount,
        uint256 _saleCount,
        uint256 _startChainId,
        uint256 _endChainId
    )
        public
        pure
        returns (bytes32)
    {
        return keccak256(
            abi.encode(
                _l1token, 
                _l2token, 
                _requestor, 
                _totalAmount, 
                _ctAmount, 
                _saleCount, 
                _startChainId, 
                _endChainId
            )
        );
    }

    // //=======Temporary view for testing ========
    // function getChainID() public view returns (uint256 id) {
    //     assembly {
    //         id := chainid()
    //     }
    // }

    //=======internal========

    /// @notice Function to calculate l1token, l2token register hash value
    function _getChainID() private view returns (uint256 id) {
        assembly {
            id := chainid()
        }
    }

    /// @notice Token transaction request
    /// @param _l1token l1token Address
    /// @param _l2token l2token Address
    /// @param _totalAmount Amount provided to L2
    /// @param _ctAmount Amount to be received from L1
    /// @param _saleCount Number generated upon request
    /// @param _endChainId chainId of l1token
    function _request(
        address _l1token,
        address _l2token,
        uint256 _totalAmount,
        uint256 _ctAmount,
        uint256 _saleCount,
        uint256 _endChainId
    )
        private
        returns (bytes32 hashValue)
    {
        if (_l2token == legacyERC20ETH) {
            require(msg.value == _totalAmount, "CT: nativeTON need amount");
        } else {
            IERC20(_l2token).safeTransferFrom(msg.sender,address(this),_totalAmount);
        }

        uint256 startChainId = _getChainID();

        hashValue = getHash(
            _l1token,
            _l2token,
            msg.sender,
            _totalAmount,
            _ctAmount,
            _saleCount,
            startChainId,
            _endChainId
        );

        dealData[_saleCount] = RequestData({
            l1token: _l1token,
            l2token: _l2token,
            requester: msg.sender,
            provider: address(0),
            totalAmount: _totalAmount,
            ctAmount: _ctAmount,
            chainId: _endChainId,
            hashValue: hashValue
        });

    }
}
        

@openzeppelin/contracts/utils/introspection/IERC165.sol

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

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * 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[EIP 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);
}
          

@openzeppelin/contracts/access/AccessControl.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}
          

@openzeppelin/contracts/access/IAccessControl.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}
          

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
          

@openzeppelin/contracts/utils/introspection/ERC165.sol

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

pragma solidity ^0.8.20;

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

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}
          

contracts/L2/L2CrossTradeStorage.sol

// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.24;

contract L2CrossTradeStorage {
    struct RequestData {
        address l1token;
        address l2token;
        address requester;
        address provider;
        uint256 totalAmount;
        uint256 ctAmount;
        uint256 chainId;
        bytes32 hashValue;
    }

    struct ChainIdData {
        address l1CrossTradeContract;
        address l1TON;
    }

    address public crossDomainMessenger;
    address public legacyERC20ETH;

    uint256 public saleCount;

    //saleCount => ChainData
    mapping(uint256 => RequestData) public dealData;
    mapping(uint256 => mapping(address => mapping(address => bool))) public registerCheck;
    
    //chainId => ChainData
    mapping(uint256 => ChainIdData) public chainData;

}
          

contracts/common/AccessRoleCommon.sol

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

contract AccessRoleCommon {
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");
    bytes32 public constant POLICY_ROLE = keccak256("POLICY_ROLE");
}
          

contracts/common/AccessibleCommon.sol

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

import "@openzeppelin/contracts/access/AccessControl.sol";
import "./AccessRoleCommon.sol";

contract AccessibleCommon is AccessRoleCommon, AccessControl {
    modifier onlyOwner() {
        require(isAdmin(msg.sender), "Accessible: Caller is not an admin");
        _;
    }

    /// @dev add admin
    /// @param account  address to add
    function addAdmin(address account) public virtual onlyOwner {
        grantRole(ADMIN_ROLE, account);
    }

    /// @dev remove admin
    /// @param account  address to remove
    function removeAdmin(address account) public virtual onlyOwner {
        renounceRole(ADMIN_ROLE, account);
    }

    /// @dev transfer admin
    /// @param newAdmin new admin address
    function transferAdmin(address newAdmin) external virtual onlyOwner {
        require(newAdmin != address(0), "Accessible: zero address");
        require(msg.sender != newAdmin, "Accessible: same admin");

        grantRole(ADMIN_ROLE, newAdmin);
        renounceRole(ADMIN_ROLE, msg.sender);
    }

    /// @dev whether admin
    /// @param account  address to check
    function isAdmin(address account) public view virtual returns (bool) {
        return hasRole(ADMIN_ROLE, account);
    }
}
          

contracts/interfaces/IERC20.sol

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

interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    function mint(address account, uint256 amount) external returns (bool);

    function burn(address account, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}
          

contracts/interfaces/IL2CrossDomainMessenger.sol

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

interface IL2CrossDomainMessenger {
    function xDomainMessageSender() 
        external 
        view 
        returns (address);
}
          

contracts/interfaces/IOptimismMintableERC20.sol

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

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

/// @title IOptimismMintableERC20
/// @notice This interface is available on the OptimismMintableERC20 contract.
///         We declare it as a separate interface so that it can be used in
///         custom implementations of OptimismMintableERC20.
interface IOptimismMintableERC20 is IERC165 {
    function remoteToken() external view returns (address);

    function bridge() external returns (address);

    function mint(address _to, uint256 _amount) external;

    function burn(address _from, uint256 _amount) external;
}

/// @custom:legacy
/// @title ILegacyMintableERC20
/// @notice This interface was available on the legacy L2StandardERC20 contract.
///         It remains available on the OptimismMintableERC20 contract for
///         backwards compatibility.
interface ILegacyMintableERC20 is IERC165 {
    function l1Token() external view returns (address);

    function mint(address _to, uint256 _amount) external;

    function burn(address _from, uint256 _amount) external;
}
          

contracts/libraries/SafeERC20.sol

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.7.5;

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

/// @notice Safe IERC20 and ETH transfer library that safely handles missing return values.
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/libraries/TransferHelper.sol)
/// Taken from Solmate
library SafeERC20 {
    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        (bool success, bytes memory data) = address(token).call(
            abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, amount)
        );

        require(success && (data.length == 0 || abi.decode(data, (bool))), "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        (bool success, bytes memory data) = address(token).call(
            abi.encodeWithSelector(IERC20.transfer.selector, to, amount)
        );

        require(success && (data.length == 0 || abi.decode(data, (bool))), "TRANSFER_FAILED");
    }

    function safeApprove(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        (bool success, bytes memory data) = address(token).call(
            abi.encodeWithSelector(IERC20.approve.selector, to, amount)
        );

        require(success && (data.length == 0 || abi.decode(data, (bool))), "APPROVE_FAILED");
    }

    function safeTransferETH(address to, uint256 amount) internal {
        (bool success, ) = to.call{value: amount}(new bytes(0));

        require(success, "ETH_TRANSFER_FAILED");
    }
}
          

contracts/proxy/ProxyStorage.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.20;

contract ProxyStorage  {

    bool public pauseProxy;

    mapping(uint256 => address) public proxyImplementation;
    mapping(address => bool) public aliveImplementation;
    mapping(bytes4 => address) public selectorImplementation;

}
          

contracts/utils/ReentrancyGuard.sol

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

pragma solidity ^0.8.20;

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

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

    uint256 private _status;

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

    constructor() {
        _status = NOT_ENTERED;
    }

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

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

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

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

    /**
     * @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 _status == ENTERED;
    }
}
          

Compiler Settings

{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":100000000,"enabled":true,"details":{"yul":true}},"libraries":{},"evmVersion":"paris"}
              

Contract ABI

[{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"bytes32","name":"neededRole","internalType":"bytes32"}]},{"type":"error","name":"ReentrancyGuardReentrantCall","inputs":[]},{"type":"event","name":"CancelCT","inputs":[{"type":"address","name":"_requester","internalType":"address","indexed":false},{"type":"uint256","name":"_totalAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_saleCount","internalType":"uint256","indexed":true},{"type":"uint256","name":"_l2chainId","internalType":"uint256","indexed":false},{"type":"bytes32","name":"_hash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"NonRequestCT","inputs":[{"type":"address","name":"_l1token","internalType":"address","indexed":false},{"type":"address","name":"_l2token","internalType":"address","indexed":false},{"type":"address","name":"_requester","internalType":"address","indexed":false},{"type":"uint256","name":"_totalAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_ctAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_saleCount","internalType":"uint256","indexed":true},{"type":"uint256","name":"_l2chainId","internalType":"uint256","indexed":false},{"type":"bytes32","name":"_hashValue","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"ProviderClaimCT","inputs":[{"type":"address","name":"_l1token","internalType":"address","indexed":false},{"type":"address","name":"_l2token","internalType":"address","indexed":false},{"type":"address","name":"_requester","internalType":"address","indexed":false},{"type":"address","name":"_provider","internalType":"address","indexed":false},{"type":"uint256","name":"_totalAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_ctAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_saleCount","internalType":"uint256","indexed":true},{"type":"uint256","name":"_l2chainId","internalType":"uint256","indexed":false},{"type":"bytes32","name":"_hash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"RequestCT","inputs":[{"type":"address","name":"_l1token","internalType":"address","indexed":false},{"type":"address","name":"_l2token","internalType":"address","indexed":false},{"type":"address","name":"_requester","internalType":"address","indexed":false},{"type":"uint256","name":"_totalAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_ctAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_saleCount","internalType":"uint256","indexed":true},{"type":"uint256","name":"_l2chainId","internalType":"uint256","indexed":false},{"type":"bytes32","name":"_hashValue","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"previousAdminRole","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"newAdminRole","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DEFAULT_ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"POLICY_ROLE","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addAdmin","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"aliveImplementation","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelCT","inputs":[{"type":"address","name":"_msgSender","internalType":"address"},{"type":"uint256","name":"_salecount","internalType":"uint256"},{"type":"uint256","name":"_chainId","internalType":"uint256"},{"type":"bytes32","name":"_hash","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelOwnerCT","inputs":[{"type":"address","name":"_msgSender","internalType":"address"},{"type":"uint256","name":"_salecount","internalType":"uint256"},{"type":"uint256","name":"_chainId","internalType":"uint256"},{"type":"bytes32","name":"_hash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"l1CrossTradeContract","internalType":"address"},{"type":"address","name":"l1TON","internalType":"address"}],"name":"chainData","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"modify","internalType":"uint256"}],"name":"checkModify","inputs":[{"type":"address","name":"_crossDomainMessenger","internalType":"address"},{"type":"address","name":"_xDomainMessageSender","internalType":"address"},{"type":"uint256","name":"_chainId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimCT","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_ctAmount","internalType":"uint256"},{"type":"uint256","name":"_saleCount","internalType":"uint256"},{"type":"uint256","name":"_chainId","internalType":"uint256"},{"type":"bytes32","name":"_hash","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimOwnerCT","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_ctAmount","internalType":"uint256"},{"type":"uint256","name":"_saleCount","internalType":"uint256"},{"type":"uint256","name":"_chainId","internalType":"uint256"},{"type":"bytes32","name":"_hash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"crossDomainMessenger","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"l1token","internalType":"address"},{"type":"address","name":"l2token","internalType":"address"},{"type":"address","name":"requester","internalType":"address"},{"type":"address","name":"provider","internalType":"address"},{"type":"uint256","name":"totalAmount","internalType":"uint256"},{"type":"uint256","name":"ctAmount","internalType":"uint256"},{"type":"uint256","name":"chainId","internalType":"uint256"},{"type":"bytes32","name":"hashValue","internalType":"bytes32"}],"name":"dealData","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteToken","inputs":[{"type":"address","name":"_l1token","internalType":"address"},{"type":"address","name":"_l2token","internalType":"address"},{"type":"uint256","name":"_l1chainId","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getHash","inputs":[{"type":"address","name":"_l1token","internalType":"address"},{"type":"address","name":"_l2token","internalType":"address"},{"type":"address","name":"_requestor","internalType":"address"},{"type":"uint256","name":"_totalAmount","internalType":"uint256"},{"type":"uint256","name":"_ctAmount","internalType":"uint256"},{"type":"uint256","name":"_saleCount","internalType":"uint256"},{"type":"uint256","name":"_startChainId","internalType":"uint256"},{"type":"uint256","name":"_endChainId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRoleAdmin","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isAdmin","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"legacyERC20ETH","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"pauseProxy","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"proxyImplementation","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"registerCheck","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"registerToken","inputs":[{"type":"address","name":"_l1token","internalType":"address"},{"type":"address","name":"_l2token","internalType":"address"},{"type":"uint256","name":"_l1chainId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeAdmin","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"callerConfirmation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"requestNonRegisteredToken","inputs":[{"type":"address","name":"_l1token","internalType":"address"},{"type":"address","name":"_l2token","internalType":"address"},{"type":"uint256","name":"_totalAmount","internalType":"uint256"},{"type":"uint256","name":"_ctAmount","internalType":"uint256"},{"type":"uint256","name":"_l1chainId","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"requestRegisteredToken","inputs":[{"type":"address","name":"_l1token","internalType":"address"},{"type":"address","name":"_l2token","internalType":"address"},{"type":"uint256","name":"_totalAmount","internalType":"uint256"},{"type":"uint256","name":"_ctAmount","internalType":"uint256"},{"type":"uint256","name":"_l1chainId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"saleCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"selectorImplementation","inputs":[{"type":"bytes4","name":"","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferAdmin","inputs":[{"type":"address","name":"newAdmin","internalType":"address"}]}]
              

Contract Creation Code

Verify & Publish
0x6080806040523461001b576001600b556126c590816100218239f35b600080fdfe608060408181526004908136101561001657600080fd5b600092833560e01c90816301ffc9a7146117c5575080630f377395146116ce57806316019f4d1461164057806316e01724146115ed5780631785f53c146115725780632298524614611519578063248a9ca3146114d157806324d7806c146114415780632f2ff15d146113f857806336568abe1461136d57806350d2a276146112e7578063550d01a3146112805780635988ec501461101857806363a8fd8914610fd85780637048027514610f4757806375829def14610dc657806375b238fc14610d6d57806381f331da14610bc75780638800867b14610b435780638a020c6714610ad957806391d1485414610a695780639792f8d714610938578063a1e89aec146108fb578063a217fddf146108c2578063b6f7134b1461078f578063b911135f14610733578063cd4618af14610710578063d547741f146106b3578063ddf0cbf4146105e1578063e59f69c214610579578063f43b361314610522578063f5869c2f146104665763fc9dc1861461018f57600080fd5b346104625761019d3661194d565b929391946101a9611f2d565b8073ffffffffffffffffffffffffffffffffffffffff9283600554169081331491826103c9575b50506101dc9150611b0a565b858752602090600882526101f8836003868b2001541615611b6f565b86885260088252826002858a200154169583811680970361036d578789526008835261022b866007878c20015414611bd4565b878952600883528489209360038501887fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905580600184870154960154169060065416811460001461033357505087808080868a5af161028d611c39565b50156102d8575091608093917f62d1466ea7dfd1b476db9e90a17828c8bb0fc5a57df551bf584a7f8a354878b495935b825194855284015246908301526060820152a26001600b5580f35b6064918451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601260248201527f63616e63656c20726566756e64206661696c00000000000000000000000000006044820152fd5b846080979593507f62d1466ea7dfd1b476db9e90a17828c8bb0fc5a57df551bf584a7f8a354878b49896949261036892611f80565b6102bd565b506064918451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600f60248201527f796f7572206e6f742073656c6c657200000000000000000000000000000000006044820152fd5b60209192508651938480927f6e296e450000000000000000000000000000000000000000000000000000000082525afa91821561045857906101dc92918a92610427575b508952600a6020528380868b2054169116148291386101d0565b61044a91925060203d602011610451575b6104428183611a6e565b810190611ade565b903861040d565b503d610438565b85513d8b823e3d90fd5b8280fd5b50823461051f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261051f5782358152600860209081529082902080546001820154600283015460038401549684015460058501546006860154600790960154975173ffffffffffffffffffffffffffffffffffffffff9586168152938516968401969096529083166040830152919095166060860152608085015260a084019190915260c083015260e082015261010090f35b80fd5b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760209073ffffffffffffffffffffffffffffffffffffffff600554169051908152f35b5080fd5b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257918192358152600a6020522073ffffffffffffffffffffffffffffffffffffffff6001818354169201541682519182526020820152f35b83827f9234c0bc9ec97c418266f9342cc42597ee66dc6f1c718161a25a8b8ba660d3e76106a8610656610613366119a6565b61062596949591939296323314611d75565b610630871515611e00565b61063b841515611e00565b610643611f2d565b60016007540180600755848885896123fa565b600754975173ffffffffffffffffffffffffffffffffffffffff9586168152919094166020820152336040820152606081019490945260808401524660a084015260c0830191909152819060e0820190565b0390a26001600b5580f35b50903461046257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104625761070c9161070760018335926106f76118aa565b948488526020528620015461209e565b612357565b5080f35b8382346105755760209061072c61072636611a0e565b91611edd565b9051908152f35b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610462578160209373ffffffffffffffffffffffffffffffffffffffff92358152600185522054169051908152f35b5090346104625761079f36611a0e565b7fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec4286949392945260209280845285872033885284526107e360ff8789205416611c97565b818752600984528587209273ffffffffffffffffffffffffffffffffffffffff809116938489528552868820951694858852845260ff86882054166108665750855260098252838520908552815282842091845252812060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905580f35b606490848751917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601560248201527f616c7265616479207265676973746572546f6b656e00000000000000000000006044820152fd5b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755751908152602090f35b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610575576020906007549051908152f35b5090346104625761094836611a0e565b7fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec42869493929452602092808452858720338852845261098c60ff8789205416611c97565b818752600984528587209273ffffffffffffffffffffffffffffffffffffffff809116938489528552868820951694858852845260ff868820541615610a0d575085526009825283852090855281528284209184525281207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905580f35b606490848751917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601360248201527f616c72656164792064656c657465546f6b656e000000000000000000000000006044820152fd5b50903461046257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610462578160209360ff92610aa86118aa565b9080358352865273ffffffffffffffffffffffffffffffffffffffff83832091168252855220541690519015158152f35b838234610575576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760209061072c610b19611882565b610b216118aa565b90610b2a6118cd565b60e4359260c4359260a435926084359260643592611e65565b5090346104625760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610462578160209360ff92610b836118aa565b610b8b6118cd565b913583526009875283832073ffffffffffffffffffffffffffffffffffffffff8092168452875283832091168252855220541690519015158152f35b508290610bd3366119a6565b9096610be494939294323314611d75565b610bef851515611e00565b610bfa881515611e00565b610c02611f2d565b818752600960205285872073ffffffffffffffffffffffffffffffffffffffff9081861689526020528688209084168852602052600160ff8789205416151503610d1057878510610c8d5750956106a8916106567f4ed7594528ea467b40aa40eeff1ebf7a53cd3771da17f533517dcd207b18b07796979860016007540180600755848885896123fa565b60849060208751917f08c379a0000000000000000000000000000000000000000000000000000000008352820152603360248201527f54686520746f74616c416d6f756e742076616c7565206d75737420626520677260448201527f6561746572207468616e206374416d6f756e74000000000000000000000000006064820152fd5b60649060208751917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601260248201527f6e6f7420726567697374657220746f6b656e00000000000000000000000000006044820152fd5b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261057557602090517fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec428152f35b5091903461057557602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257610e02611882565b917fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec428085528282528585203386528252610e4160ff8787205416611c97565b73ffffffffffffffffffffffffffffffffffffffff84168015610eeb573314610e8f5794610e7d926001928697610e829752528520015461209e565b6120fb565b50610e8c33611d22565b80f35b606483838851917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601660248201527f41636365737369626c653a2073616d652061646d696e000000000000000000006044820152fd5b606484848951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601860248201527f41636365737369626c653a207a65726f206164647265737300000000000000006044820152fd5b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257610e7d600161070c93610f89611882565b937fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec4280885281602052828820338952602052610fca60ff848a205416611c97565b87526020528520015461209e565b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760ff602092541690519015158152f35b5091903461057557611029366118f0565b969391949290507fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec428652602092808452848720338852845261107060ff8689205416611c97565b611078611f2d565b8587526008845273ffffffffffffffffffffffffffffffffffffffff926110a7846003888b2001541615611b6f565b868852600885526110bf896007888b20015414611bd4565b821561126b575b8688526008855285882094600386019285831693847fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790558086600189015416970154938660065416881460001461122b578a80808781945af161112c611c39565b50156111d05750917ff8cde1fe2cd0b62a858b3e46ed74ad19f4de0483236632b75745d688c727af20979899939160086106a896945b8b8d5252878b20936002818654169501541697519788974695899491909360e096939998979461010087019a73ffffffffffffffffffffffffffffffffffffffff8094818094168a52166020890152166040870152166060850152608084015260a083015260c08201520152565b6064918851917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600a60248201527f636c61696d206661696c000000000000000000000000000000000000000000006044820152fd5b5050918160086106a89694611266847ff8cde1fe2cd0b62a858b3e46ed74ad19f4de0483236632b75745d688c727af209c9d9e98968b611f80565b611162565b868852600885528588206005015492506110c6565b8382346105755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760ff8160209373ffffffffffffffffffffffffffffffffffffffff6112d4611882565b1681526002855220541690519015158152f35b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257357fffffffff00000000000000000000000000000000000000000000000000000000811680910361046257818373ffffffffffffffffffffffffffffffffffffffff9260209552600385522054169051908152f35b5082903461057557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610575576113a66118aa565b903373ffffffffffffffffffffffffffffffffffffffff8316036113d0575061070c919235612357565b8390517f6697b232000000000000000000000000000000000000000000000000000000008152fd5b50903461046257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104625761070c9161143c60018335926106f76118aa565b6121d9565b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610462578160209360ff92611481611882565b907fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec428352865273ffffffffffffffffffffffffffffffffffffffff83832091168252855220541690519015158152f35b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257816020938260019335825285522001549051908152f35b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261057557602090517ffb5864e8ff833c3cb2d2d08505e82ff02a43554c74a35d4f5a64e852612783118152f35b833461051f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261051f57610e8c6115ad611882565b3360009081527f2fb794d17134dfdec181ddbac1babb5ab1eb140204ef4d982f294e7fc8b6902260205260409020546115e89060ff16611c97565b611d22565b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760209073ffffffffffffffffffffffffffffffffffffffff600654169051908152f35b50346104625761164f3661194d565b3360009081527f2fb794d17134dfdec181ddbac1babb5ab1eb140204ef4d982f294e7fc8b69022602052604090205492959394909390929091506116959060ff16611c97565b61169d611f2d565b84865260206008815273ffffffffffffffffffffffffffffffffffffffff916101f8836003868b2001541615611b6f565b50919034610575576116df366118f0565b9693929091946116ed611f2d565b8073ffffffffffffffffffffffffffffffffffffffff93846005541690813314918261173c575b50506117209150611b0a565b858752602093600885526110a7846003888b2001541615611b6f565b60209192508851938480927f6e296e450000000000000000000000000000000000000000000000000000000082525afa9182156117bb579061172092918a9261179a575b508952600a6020528480888b205416911614829138611714565b6117b491925060203d602011610451576104428183611a6e565b9038611780565b87513d8b823e3d90fd5b849084346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257357fffffffff00000000000000000000000000000000000000000000000000000000811680910361046257602092507f7965db0b000000000000000000000000000000000000000000000000000000008114908115611858575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483611851565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036118a557565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff821682036118a557565b6044359073ffffffffffffffffffffffffffffffffffffffff821682036118a557565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a09101126118a55760043573ffffffffffffffffffffffffffffffffffffffff811681036118a5579060243590604435906064359060843590565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60809101126118a55760043573ffffffffffffffffffffffffffffffffffffffff811681036118a55790602435906044359060643590565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a09101126118a55773ffffffffffffffffffffffffffffffffffffffff9060043582811681036118a5579160243590811681036118a55790604435906064359060843590565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126118a55773ffffffffffffffffffffffffffffffffffffffff9060043582811681036118a5579160243590811681036118a5579060443590565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117611aaf57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b908160209103126118a5575173ffffffffffffffffffffffffffffffffffffffff811681036118a55790565b15611b1157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6f6e6c792063616c6c206c3146617374576974686472617700000000000000006044820152fd5b15611b7657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f616c726561647920736f6c6400000000000000000000000000000000000000006044820152fd5b15611bdb57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f486173682076616c75657320646f206e6f74206d6174636800000000000000006044820152fd5b3d15611c92573d9067ffffffffffffffff8211611aaf5760405191611c8660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184611a6e565b82523d6000602084013e565b606090565b15611c9e57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f41636365737369626c653a2043616c6c6572206973206e6f7420616e2061646d60448201527f696e0000000000000000000000000000000000000000000000000000000000006064820152fd5b3373ffffffffffffffffffffffffffffffffffffffff821603611d4b57611d4890612280565b50565b60046040517f6697b232000000000000000000000000000000000000000000000000000000008152fd5b15611d7c57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c3246573a2066756e6374696f6e2063616e206f6e6c792062652063616c6c6560448201527f642066726f6d20616e20454f41000000000000000000000000000000000000006064820152fd5b15611e0757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e70757420616d6f756e74206e656564206e6f6e5a65726f000000000000006044820152fd5b969492909593919560405196602088019873ffffffffffffffffffffffffffffffffffffffff92838092168b52166040890152166060870152608086015260a085015260c084015260e083015261010090818301528152610120810181811067ffffffffffffffff821117611aaf5760405251902090565b600554919273ffffffffffffffffffffffffffffffffffffffff929091831690831614611f0c57505050600190565b600052600a6020528060406000205416911603611f2857600390565b600290565b6002600b5414611f3e576002600b55565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b908160209103126118a5575180151581036118a55790565b91909173ffffffffffffffffffffffffffffffffffffffff92604051928460208501927fa9059cbb0000000000000000000000000000000000000000000000000000000084521660248501526044840152604483526080830183811067ffffffffffffffff821117611aaf57600094859485926040525193165af1612003611c39565b8161206f575b501561201157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152fd5b8051801592508215612084575b505038612009565b6120979250602080918301019101611f68565b388061207c565b80600052600460205260406000203360005260205260ff60406000205416156120c45750565b604490604051907fe2517d3f0000000000000000000000000000000000000000000000000000000082523360048301526024820152fd5b73ffffffffffffffffffffffffffffffffffffffff1660008181527f2fb794d17134dfdec181ddbac1babb5ab1eb140204ef4d982f294e7fc8b6902260205260408120549091907fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec429060ff166121d4578083526004602052604083208284526020526040832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b505090565b90600091808352600460205273ffffffffffffffffffffffffffffffffffffffff6040842092169182845260205260ff604084205416156000146121d4578083526004602052604083208284526020526040832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b73ffffffffffffffffffffffffffffffffffffffff1660008181527f2fb794d17134dfdec181ddbac1babb5ab1eb140204ef4d982f294e7fc8b6902260205260408120549091907fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec429060ff16156121d457808352600460205260408320828452602052604083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b90600091808352600460205273ffffffffffffffffffffffffffffffffffffffff6040842092169182845260205260ff6040842054166000146121d457808352600460205260408320828452602052604083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b9295949093919573ffffffffffffffffffffffffffffffffffffffff9687600654169588811696871460001461257e578134036125205783612444915b868585469333908c611e65565b9760405196610100880188811067ffffffffffffffff821117611aaf57600797839160405216885260208801908152604088019133835260608901926000845260808a0194855260a08a0195865260c08a0196875260e08a01978c895260005260086020528160406000209a5116927fffffffffffffffffffffffff000000000000000000000000000000000000000093848c5416178b558260018c01915116848254161790558160028b0191511683825416179055600389019251169082541617905551600486015551600585015551600684015551910155565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f43543a206e6174697665544f4e206e65656420616d6f756e74000000000000006044820152fd5b604051602081017f23b872dd0000000000000000000000000000000000000000000000000000000081523360248301523060448301528360648301526064825260a082019082821067ffffffffffffffff831117611aaf5760009283926040525190828b5af16125ec611c39565b81612660575b5015612602578361244491612437565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b8051801592508215612675575b5050386125f2565b6126889250602080918301019101611f68565b388061266d56fea26469706673582212205c076140fd0de0d6c40493c8274b4c0c1cbcd97474c56644d3d6b7bff43d3dfa64736f6c63430008180033

Deployed ByteCode

0x608060408181526004908136101561001657600080fd5b600092833560e01c90816301ffc9a7146117c5575080630f377395146116ce57806316019f4d1461164057806316e01724146115ed5780631785f53c146115725780632298524614611519578063248a9ca3146114d157806324d7806c146114415780632f2ff15d146113f857806336568abe1461136d57806350d2a276146112e7578063550d01a3146112805780635988ec501461101857806363a8fd8914610fd85780637048027514610f4757806375829def14610dc657806375b238fc14610d6d57806381f331da14610bc75780638800867b14610b435780638a020c6714610ad957806391d1485414610a695780639792f8d714610938578063a1e89aec146108fb578063a217fddf146108c2578063b6f7134b1461078f578063b911135f14610733578063cd4618af14610710578063d547741f146106b3578063ddf0cbf4146105e1578063e59f69c214610579578063f43b361314610522578063f5869c2f146104665763fc9dc1861461018f57600080fd5b346104625761019d3661194d565b929391946101a9611f2d565b8073ffffffffffffffffffffffffffffffffffffffff9283600554169081331491826103c9575b50506101dc9150611b0a565b858752602090600882526101f8836003868b2001541615611b6f565b86885260088252826002858a200154169583811680970361036d578789526008835261022b866007878c20015414611bd4565b878952600883528489209360038501887fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905580600184870154960154169060065416811460001461033357505087808080868a5af161028d611c39565b50156102d8575091608093917f62d1466ea7dfd1b476db9e90a17828c8bb0fc5a57df551bf584a7f8a354878b495935b825194855284015246908301526060820152a26001600b5580f35b6064918451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601260248201527f63616e63656c20726566756e64206661696c00000000000000000000000000006044820152fd5b846080979593507f62d1466ea7dfd1b476db9e90a17828c8bb0fc5a57df551bf584a7f8a354878b49896949261036892611f80565b6102bd565b506064918451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600f60248201527f796f7572206e6f742073656c6c657200000000000000000000000000000000006044820152fd5b60209192508651938480927f6e296e450000000000000000000000000000000000000000000000000000000082525afa91821561045857906101dc92918a92610427575b508952600a6020528380868b2054169116148291386101d0565b61044a91925060203d602011610451575b6104428183611a6e565b810190611ade565b903861040d565b503d610438565b85513d8b823e3d90fd5b8280fd5b50823461051f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261051f5782358152600860209081529082902080546001820154600283015460038401549684015460058501546006860154600790960154975173ffffffffffffffffffffffffffffffffffffffff9586168152938516968401969096529083166040830152919095166060860152608085015260a084019190915260c083015260e082015261010090f35b80fd5b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760209073ffffffffffffffffffffffffffffffffffffffff600554169051908152f35b5080fd5b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257918192358152600a6020522073ffffffffffffffffffffffffffffffffffffffff6001818354169201541682519182526020820152f35b83827f9234c0bc9ec97c418266f9342cc42597ee66dc6f1c718161a25a8b8ba660d3e76106a8610656610613366119a6565b61062596949591939296323314611d75565b610630871515611e00565b61063b841515611e00565b610643611f2d565b60016007540180600755848885896123fa565b600754975173ffffffffffffffffffffffffffffffffffffffff9586168152919094166020820152336040820152606081019490945260808401524660a084015260c0830191909152819060e0820190565b0390a26001600b5580f35b50903461046257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104625761070c9161070760018335926106f76118aa565b948488526020528620015461209e565b612357565b5080f35b8382346105755760209061072c61072636611a0e565b91611edd565b9051908152f35b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610462578160209373ffffffffffffffffffffffffffffffffffffffff92358152600185522054169051908152f35b5090346104625761079f36611a0e565b7fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec4286949392945260209280845285872033885284526107e360ff8789205416611c97565b818752600984528587209273ffffffffffffffffffffffffffffffffffffffff809116938489528552868820951694858852845260ff86882054166108665750855260098252838520908552815282842091845252812060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905580f35b606490848751917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601560248201527f616c7265616479207265676973746572546f6b656e00000000000000000000006044820152fd5b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755751908152602090f35b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610575576020906007549051908152f35b5090346104625761094836611a0e565b7fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec42869493929452602092808452858720338852845261098c60ff8789205416611c97565b818752600984528587209273ffffffffffffffffffffffffffffffffffffffff809116938489528552868820951694858852845260ff868820541615610a0d575085526009825283852090855281528284209184525281207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905580f35b606490848751917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601360248201527f616c72656164792064656c657465546f6b656e000000000000000000000000006044820152fd5b50903461046257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610462578160209360ff92610aa86118aa565b9080358352865273ffffffffffffffffffffffffffffffffffffffff83832091168252855220541690519015158152f35b838234610575576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760209061072c610b19611882565b610b216118aa565b90610b2a6118cd565b60e4359260c4359260a435926084359260643592611e65565b5090346104625760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610462578160209360ff92610b836118aa565b610b8b6118cd565b913583526009875283832073ffffffffffffffffffffffffffffffffffffffff8092168452875283832091168252855220541690519015158152f35b508290610bd3366119a6565b9096610be494939294323314611d75565b610bef851515611e00565b610bfa881515611e00565b610c02611f2d565b818752600960205285872073ffffffffffffffffffffffffffffffffffffffff9081861689526020528688209084168852602052600160ff8789205416151503610d1057878510610c8d5750956106a8916106567f4ed7594528ea467b40aa40eeff1ebf7a53cd3771da17f533517dcd207b18b07796979860016007540180600755848885896123fa565b60849060208751917f08c379a0000000000000000000000000000000000000000000000000000000008352820152603360248201527f54686520746f74616c416d6f756e742076616c7565206d75737420626520677260448201527f6561746572207468616e206374416d6f756e74000000000000000000000000006064820152fd5b60649060208751917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601260248201527f6e6f7420726567697374657220746f6b656e00000000000000000000000000006044820152fd5b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261057557602090517fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec428152f35b5091903461057557602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257610e02611882565b917fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec428085528282528585203386528252610e4160ff8787205416611c97565b73ffffffffffffffffffffffffffffffffffffffff84168015610eeb573314610e8f5794610e7d926001928697610e829752528520015461209e565b6120fb565b50610e8c33611d22565b80f35b606483838851917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601660248201527f41636365737369626c653a2073616d652061646d696e000000000000000000006044820152fd5b606484848951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601860248201527f41636365737369626c653a207a65726f206164647265737300000000000000006044820152fd5b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257610e7d600161070c93610f89611882565b937fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec4280885281602052828820338952602052610fca60ff848a205416611c97565b87526020528520015461209e565b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760ff602092541690519015158152f35b5091903461057557611029366118f0565b969391949290507fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec428652602092808452848720338852845261107060ff8689205416611c97565b611078611f2d565b8587526008845273ffffffffffffffffffffffffffffffffffffffff926110a7846003888b2001541615611b6f565b868852600885526110bf896007888b20015414611bd4565b821561126b575b8688526008855285882094600386019285831693847fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790558086600189015416970154938660065416881460001461122b578a80808781945af161112c611c39565b50156111d05750917ff8cde1fe2cd0b62a858b3e46ed74ad19f4de0483236632b75745d688c727af20979899939160086106a896945b8b8d5252878b20936002818654169501541697519788974695899491909360e096939998979461010087019a73ffffffffffffffffffffffffffffffffffffffff8094818094168a52166020890152166040870152166060850152608084015260a083015260c08201520152565b6064918851917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600a60248201527f636c61696d206661696c000000000000000000000000000000000000000000006044820152fd5b5050918160086106a89694611266847ff8cde1fe2cd0b62a858b3e46ed74ad19f4de0483236632b75745d688c727af209c9d9e98968b611f80565b611162565b868852600885528588206005015492506110c6565b8382346105755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760ff8160209373ffffffffffffffffffffffffffffffffffffffff6112d4611882565b1681526002855220541690519015158152f35b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257357fffffffff00000000000000000000000000000000000000000000000000000000811680910361046257818373ffffffffffffffffffffffffffffffffffffffff9260209552600385522054169051908152f35b5082903461057557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610575576113a66118aa565b903373ffffffffffffffffffffffffffffffffffffffff8316036113d0575061070c919235612357565b8390517f6697b232000000000000000000000000000000000000000000000000000000008152fd5b50903461046257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104625761070c9161143c60018335926106f76118aa565b6121d9565b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610462578160209360ff92611481611882565b907fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec428352865273ffffffffffffffffffffffffffffffffffffffff83832091168252855220541690519015158152f35b5090346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257816020938260019335825285522001549051908152f35b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261057557602090517ffb5864e8ff833c3cb2d2d08505e82ff02a43554c74a35d4f5a64e852612783118152f35b833461051f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261051f57610e8c6115ad611882565b3360009081527f2fb794d17134dfdec181ddbac1babb5ab1eb140204ef4d982f294e7fc8b6902260205260409020546115e89060ff16611c97565b611d22565b83823461057557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105755760209073ffffffffffffffffffffffffffffffffffffffff600654169051908152f35b50346104625761164f3661194d565b3360009081527f2fb794d17134dfdec181ddbac1babb5ab1eb140204ef4d982f294e7fc8b69022602052604090205492959394909390929091506116959060ff16611c97565b61169d611f2d565b84865260206008815273ffffffffffffffffffffffffffffffffffffffff916101f8836003868b2001541615611b6f565b50919034610575576116df366118f0565b9693929091946116ed611f2d565b8073ffffffffffffffffffffffffffffffffffffffff93846005541690813314918261173c575b50506117209150611b0a565b858752602093600885526110a7846003888b2001541615611b6f565b60209192508851938480927f6e296e450000000000000000000000000000000000000000000000000000000082525afa9182156117bb579061172092918a9261179a575b508952600a6020528480888b205416911614829138611714565b6117b491925060203d602011610451576104428183611a6e565b9038611780565b87513d8b823e3d90fd5b849084346104625760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261046257357fffffffff00000000000000000000000000000000000000000000000000000000811680910361046257602092507f7965db0b000000000000000000000000000000000000000000000000000000008114908115611858575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483611851565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036118a557565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff821682036118a557565b6044359073ffffffffffffffffffffffffffffffffffffffff821682036118a557565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a09101126118a55760043573ffffffffffffffffffffffffffffffffffffffff811681036118a5579060243590604435906064359060843590565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60809101126118a55760043573ffffffffffffffffffffffffffffffffffffffff811681036118a55790602435906044359060643590565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a09101126118a55773ffffffffffffffffffffffffffffffffffffffff9060043582811681036118a5579160243590811681036118a55790604435906064359060843590565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126118a55773ffffffffffffffffffffffffffffffffffffffff9060043582811681036118a5579160243590811681036118a5579060443590565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117611aaf57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b908160209103126118a5575173ffffffffffffffffffffffffffffffffffffffff811681036118a55790565b15611b1157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6f6e6c792063616c6c206c3146617374576974686472617700000000000000006044820152fd5b15611b7657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f616c726561647920736f6c6400000000000000000000000000000000000000006044820152fd5b15611bdb57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f486173682076616c75657320646f206e6f74206d6174636800000000000000006044820152fd5b3d15611c92573d9067ffffffffffffffff8211611aaf5760405191611c8660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184611a6e565b82523d6000602084013e565b606090565b15611c9e57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f41636365737369626c653a2043616c6c6572206973206e6f7420616e2061646d60448201527f696e0000000000000000000000000000000000000000000000000000000000006064820152fd5b3373ffffffffffffffffffffffffffffffffffffffff821603611d4b57611d4890612280565b50565b60046040517f6697b232000000000000000000000000000000000000000000000000000000008152fd5b15611d7c57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c3246573a2066756e6374696f6e2063616e206f6e6c792062652063616c6c6560448201527f642066726f6d20616e20454f41000000000000000000000000000000000000006064820152fd5b15611e0757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e70757420616d6f756e74206e656564206e6f6e5a65726f000000000000006044820152fd5b969492909593919560405196602088019873ffffffffffffffffffffffffffffffffffffffff92838092168b52166040890152166060870152608086015260a085015260c084015260e083015261010090818301528152610120810181811067ffffffffffffffff821117611aaf5760405251902090565b600554919273ffffffffffffffffffffffffffffffffffffffff929091831690831614611f0c57505050600190565b600052600a6020528060406000205416911603611f2857600390565b600290565b6002600b5414611f3e576002600b55565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b908160209103126118a5575180151581036118a55790565b91909173ffffffffffffffffffffffffffffffffffffffff92604051928460208501927fa9059cbb0000000000000000000000000000000000000000000000000000000084521660248501526044840152604483526080830183811067ffffffffffffffff821117611aaf57600094859485926040525193165af1612003611c39565b8161206f575b501561201157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152fd5b8051801592508215612084575b505038612009565b6120979250602080918301019101611f68565b388061207c565b80600052600460205260406000203360005260205260ff60406000205416156120c45750565b604490604051907fe2517d3f0000000000000000000000000000000000000000000000000000000082523360048301526024820152fd5b73ffffffffffffffffffffffffffffffffffffffff1660008181527f2fb794d17134dfdec181ddbac1babb5ab1eb140204ef4d982f294e7fc8b6902260205260408120549091907fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec429060ff166121d4578083526004602052604083208284526020526040832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b505090565b90600091808352600460205273ffffffffffffffffffffffffffffffffffffffff6040842092169182845260205260ff604084205416156000146121d4578083526004602052604083208284526020526040832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b73ffffffffffffffffffffffffffffffffffffffff1660008181527f2fb794d17134dfdec181ddbac1babb5ab1eb140204ef4d982f294e7fc8b6902260205260408120549091907fdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec429060ff16156121d457808352600460205260408320828452602052604083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b90600091808352600460205273ffffffffffffffffffffffffffffffffffffffff6040842092169182845260205260ff6040842054166000146121d457808352600460205260408320828452602052604083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b9295949093919573ffffffffffffffffffffffffffffffffffffffff9687600654169588811696871460001461257e578134036125205783612444915b868585469333908c611e65565b9760405196610100880188811067ffffffffffffffff821117611aaf57600797839160405216885260208801908152604088019133835260608901926000845260808a0194855260a08a0195865260c08a0196875260e08a01978c895260005260086020528160406000209a5116927fffffffffffffffffffffffff000000000000000000000000000000000000000093848c5416178b558260018c01915116848254161790558160028b0191511683825416179055600389019251169082541617905551600486015551600585015551600684015551910155565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f43543a206e6174697665544f4e206e65656420616d6f756e74000000000000006044820152fd5b604051602081017f23b872dd0000000000000000000000000000000000000000000000000000000081523360248301523060448301528360648301526064825260a082019082821067ffffffffffffffff831117611aaf5760009283926040525190828b5af16125ec611c39565b81612660575b5015612602578361244491612437565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b8051801592508215612675575b5050386125f2565b6126889250602080918301019101611f68565b388061266d56fea26469706673582212205c076140fd0de0d6c40493c8274b4c0c1cbcd97474c56644d3d6b7bff43d3dfa64736f6c63430008180033