ETH Price: $2,334.22 (+1.46%)
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

1 address found via
Amount:Between 1-100
Reset Filter
Transaction Hash
Block
From
To
Execute Order1097628782023-09-19 11:55:33944 days ago1695124533IN
0x9b2Ed3C2...31320aC26
3.271 ETH0.0003496760140.08448574
Execute Order1096097102023-09-15 22:49:57947 days ago1694818197IN
0x9b2Ed3C2...31320aC26
10 ETH0.0000734160760.00097051
Execute Order1087334572023-08-26 16:01:31968 days ago1693065691IN
0x9b2Ed3C2...31320aC26
2 ETH0.0001681540750.00088444
Execute Order1082191612023-08-14 18:18:19980 days ago1692037099IN
0x9b2Ed3C2...31320aC26
2.73046942429561 ETH0.0007484639280.1000001
Execute Order1078899982023-08-07 3:26:13987 days ago1691378773IN
0x9b2Ed3C2...31320aC26
13.8 ETH0.0000983511760.00000011
Execute Order1078331502023-08-05 19:51:17988 days ago1691265077IN
0x9b2Ed3C2...31320aC26
8.1777 ETH0.000406751840.1000001
Execute Order1076001442023-07-31 10:24:25994 days ago1690799065IN
0x9b2Ed3C2...31320aC26
4 ETH0.0002051252630.1
Execute Order1075432852023-07-30 2:49:07995 days ago1690685347IN
0x9b2Ed3C2...31320aC26
5.32501211440256 ETH0.0002094419990.0000219
Execute Order1075432072023-07-30 2:46:31995 days ago1690685191IN
0x9b2Ed3C2...31320aC26
5.324983758799536 ETH0.0002366734790.0000143
Execute Order1070923552023-07-19 16:18:071006 days ago1689783487IN
0x9b2Ed3C2...31320aC26
2.646330776226951 ETH0.0004682063820.00000009
Execute Order1070691502023-07-19 3:24:371006 days ago1689737077IN
0x9b2Ed3C2...31320aC26
2.7 ETH0.0001962885320.000002
Execute Order1065388502023-07-06 20:47:571018 days ago1688676477IN
0x9b2Ed3C2...31320aC26
2.1 ETH0.0001794478180.00000006
Execute Order1065386982023-07-06 20:42:531018 days ago1688676173IN
0x9b2Ed3C2...31320aC26
2.5 ETH0.000176188450.00000007
Execute Order995343332023-05-18 13:41:331068 days ago1684417293IN
0x9b2Ed3C2...31320aC26
25.4 ETH0.0005465093860.00104815
Execute Order992333222023-05-17 23:54:111068 days ago1684367651IN
0x9b2Ed3C2...31320aC26
33 ETH0.0004417029940.00104815
Execute Order992192232023-05-17 21:42:471068 days ago1684359767IN
0x9b2Ed3C2...31320aC26
20.5 ETH0.0008813436320.00104815
Execute Order991726842023-05-17 17:46:341069 days ago1684345594IN
0x9b2Ed3C2...31320aC26
1 ETH0.0007156580320.00104815
VIEW ADVANCED FILTER

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
1167884162024-02-29 3:00:09781 days ago1709175609
0x9b2Ed3C2...31320aC26
0.168308922665729 ETH
1167884162024-02-29 3:00:09781 days ago1709175609
0x9b2Ed3C2...31320aC26
0.168308922665729 ETH
1167580022024-02-28 10:06:21782 days ago1709114781
0x9b2Ed3C2...31320aC26
0.012344852680156 ETH
1167580022024-02-28 10:06:21782 days ago1709114781
0x9b2Ed3C2...31320aC26
0.012344852680156 ETH
1166889782024-02-26 19:45:33783 days ago1708976733
0x9b2Ed3C2...31320aC26
0.000545888902158 ETH
1166889782024-02-26 19:45:33783 days ago1708976733
0x9b2Ed3C2...31320aC26
0.000545888902158 ETH
1164625302024-02-21 13:57:17789 days ago1708523837
0x9b2Ed3C2...31320aC26
0.00997 ETH
1164625302024-02-21 13:57:17789 days ago1708523837
0x9b2Ed3C2...31320aC26
0.00997 ETH
1164249502024-02-20 17:04:37790 days ago1708448677
0x9b2Ed3C2...31320aC26
0.288393502275037 ETH
1164249502024-02-20 17:04:37790 days ago1708448677
0x9b2Ed3C2...31320aC26
0.288393502275037 ETH
1164202652024-02-20 14:28:27790 days ago1708439307
0x9b2Ed3C2...31320aC26
0.111361671216484 ETH
1164202652024-02-20 14:28:27790 days ago1708439307
0x9b2Ed3C2...31320aC26
0.111361671216484 ETH
1164201992024-02-20 14:26:15790 days ago1708439175
0x9b2Ed3C2...31320aC26
0.04944151247388 ETH
1164201992024-02-20 14:26:15790 days ago1708439175
0x9b2Ed3C2...31320aC26
0.04944151247388 ETH
1164175692024-02-20 12:58:35790 days ago1708433915
0x9b2Ed3C2...31320aC26
0.095575688775016 ETH
1164175692024-02-20 12:58:35790 days ago1708433915
0x9b2Ed3C2...31320aC26
0.095575688775016 ETH
1164174772024-02-20 12:55:31790 days ago1708433731
0x9b2Ed3C2...31320aC26
0.055940216360902 ETH
1164174772024-02-20 12:55:31790 days ago1708433731
0x9b2Ed3C2...31320aC26
0.055940216360902 ETH
1164135182024-02-20 10:43:33790 days ago1708425813
0x9b2Ed3C2...31320aC26
0.015943179831649 ETH
1164135182024-02-20 10:43:33790 days ago1708425813
0x9b2Ed3C2...31320aC26
0.015943179831649 ETH
1164133462024-02-20 10:37:49790 days ago1708425469
0x9b2Ed3C2...31320aC26
0.162590213386406 ETH
1164133462024-02-20 10:37:49790 days ago1708425469
0x9b2Ed3C2...31320aC26
0.162590213386406 ETH
1163725282024-02-19 11:57:13791 days ago1708343833
0x9b2Ed3C2...31320aC26
0.000513333598954 ETH
1163725282024-02-19 11:57:13791 days ago1708343833
0x9b2Ed3C2...31320aC26
0.000513333598954 ETH
1163700802024-02-19 10:35:37791 days ago1708338937
0x9b2Ed3C2...31320aC26
0.00004985 ETH
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
WidoRouter

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 2000 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.7;

import "solmate/src/utils/SafeTransferLib.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./interfaces/IWidoRouter.sol";
import "./WidoTokenManager.sol";

error SlippageTooHigh(uint256 expectedAmount, uint256 actualAmount);

/// @title Wido Router
/// @notice Zap in or out of any ERC20 token, liquid or illiquid, in a single transaction.
/// @notice DO NOT APPROVE THIS CONTRACT FOR SPENDING YOUR TOKENS.
/// @author Wido
contract WidoRouter is IWidoRouter, Ownable, ReentrancyGuard {
    using SafeTransferLib for address;
    using SafeTransferLib for ERC20;

    bytes32 private constant EIP712_DOMAIN_TYPEHASH =
        keccak256(
            abi.encodePacked("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
        );

    bytes32 private constant ORDER_TYPEHASH =
        keccak256(
            abi.encodePacked(
                "Order(OrderInput[] inputs,OrderOutput[] outputs,address user,uint32 nonce,uint32 expiration)OrderInput(address tokenAddress,uint256 amount)OrderOutput(address tokenAddress,uint256 minOutputAmount)"
            )
        );

    bytes32 private constant ORDER_INPUT_TYPEHASH =
        keccak256(abi.encodePacked("OrderInput(address tokenAddress,uint256 amount)"));

    bytes32 private constant ORDER_OUTPUT_TYPEHASH =
        keccak256(abi.encodePacked("OrderOutput(address tokenAddress,uint256 minOutputAmount)"));

    // Nonce for executing order with EIP-712 signatures.
    mapping(address => uint256) public nonces;

    // Address of the wrapped native token
    address public immutable wrappedNativeToken;

    // Address of fee bank
    address public bank;

    WidoTokenManager public immutable widoTokenManager;

    /// @notice Event emitted when the order is fulfilled
    /// @param order The order that was fulfilled
    /// @param sender The msg.sender
    /// @param recipient Recipient of the final tokens of the order
    /// @param feeBps Fee in basis points (bps)
    /// @param partner Partner address
    event FulfilledOrder(
        Order order,
        address indexed sender,
        address recipient,
        uint256 feeBps,
        address indexed partner
    );

    /// @notice Event emitted when the bank address is updated
    /// @param bank The updated address of the bank
    event SetBank(
        address bank
    );

    constructor(
        address _wrappedNativeToken,
        address _bank // uint256 _feeBps
    ) {
        require(_wrappedNativeToken != address(0) && _bank != address(0), "Addresses cannot be zero address");

        wrappedNativeToken = _wrappedNativeToken;
        bank = _bank;
        widoTokenManager = new WidoTokenManager();
    }

    /// @notice Sets the bank address
    /// @param _bank The address of the new bank
    function setBank(address _bank) external onlyOwner {
        require(_bank != address(0) && _bank != address(this), "Bank address cannot be zero address or Wido Router address");
        bank = _bank;
        emit SetBank(_bank);
    }

    /// @notice Approve a token spending
    /// @param token The ERC20 token to approve
    /// @param spender The address of the spender
    /// @param amount The minimum allowance to grant to the spender
    function _approveToken(address token, address spender, uint256 amount) internal {
        ERC20 _token = ERC20(token);
        if (_token.allowance(address(this), spender) < amount) {
            _token.safeApprove(spender, type(uint256).max);
        }
    }

    /// @notice Executes steps in the route to transfer to token
    /// @param route Step data for token transformation
    /// @dev Updates the amount in the byte data with the current balance as to not leave any dust
    /// @dev Expects step data to be properly chained for the token transformation tokenA -> tokenB -> tokenC
    function _executeSteps(Step[] calldata route) private {
        for (uint256 i = 0; i < route.length; ) {
            Step calldata step = route[i];

            require(step.targetAddress != address(widoTokenManager), "Wido: forbidden call to WidoTokenManager");

            uint256 balance;
            uint256 value;
            if (step.fromToken == address(0)) {
                value = address(this).balance;
            } else {
                value = 0;
                balance = ERC20(step.fromToken).balanceOf(address(this));
                require(balance > 0, "Not enough balance for the step");
                _approveToken(step.fromToken, step.targetAddress, balance);
            }

            bytes memory editedSwapData;
            if (step.amountIndex >= 0) {
                uint256 idx = uint256(int256(step.amountIndex));
                editedSwapData = bytes.concat(step.data[:idx], abi.encode(balance), step.data[idx + 32:]);
            } else {
                editedSwapData = step.data;
            }

            (bool success, bytes memory result) = step.targetAddress.call{value: value}(editedSwapData);
            if (!success) {
                // Next 5 lines from https://ethereum.stackexchange.com/a/83577
                if (result.length < 68) revert();
                assembly {
                    result := add(result, 0x04)
                }
                revert(abi.decode(result, (string)));
            }

            unchecked {
                i++;
            }
        }
    }

    function hash(OrderInput[] memory orderInput) internal pure returns (bytes32) {
        bytes32[] memory result = new bytes32[](orderInput.length);
        for (uint256 i = 0; i < orderInput.length; ) {
            result[i] = keccak256(abi.encode(ORDER_INPUT_TYPEHASH, orderInput[i]));
            unchecked {
                i++;
            }
        }
        return keccak256(abi.encodePacked(result));
    }

    function hash(OrderOutput[] memory orderOutput) internal pure returns (bytes32) {
        bytes32[] memory result = new bytes32[](orderOutput.length);
        for (uint256 i = 0; i < orderOutput.length; ) {
            result[i] = keccak256(abi.encode(ORDER_OUTPUT_TYPEHASH, orderOutput[i]));
            unchecked {
                i++;
            }
        }
        return keccak256(abi.encodePacked(result));
    }

    function hash(Order memory order) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    ORDER_TYPEHASH,
                    hash(order.inputs),
                    hash(order.outputs),
                    order.user,
                    order.nonce,
                    order.expiration
                )
            );
    }

    /// @notice Verifies if the order is valid
    /// @param order Order to be validated
    /// @param v v of the signature
    /// @param r r of the signature
    /// @param s s of the signature
    /// @return bool True if the order is valid
    function verifyOrder(Order calldata order, uint8 v, bytes32 r, bytes32 s) public view override returns (bool) {
        bytes32 DOMAIN_SEPARATOR = keccak256(
            abi.encode(EIP712_DOMAIN_TYPEHASH, keccak256("WidoRouter"), keccak256("1"), block.chainid, address(this))
        );
        address recoveredAddress = ECDSA.recover(
            keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, hash(order))),
            v,
            r,
            s
        );
        require(recoveredAddress != address(0) && order.user == recoveredAddress, "Invalid signature");
        require(order.nonce == nonces[order.user], "Invalid nonce");
        require(order.expiration == 0 || block.timestamp <= order.expiration, "Expired request");
        for (uint256 i = 0; i < order.inputs.length; ) {
            IWidoRouter.OrderInput calldata input = order.inputs[i];
            require(input.amount > 0, "Amount should be greater than 0");
            unchecked {
                i++;
            }
        }
        return true;
    }

    /// @notice Executes the validated order
    /// @param order Order to be executed
    /// @param route Route to execute for the token swap
    /// @param recipient The address of the final token receiver
    /// @param feeBps Fee in basis points (bps)
    /// @dev Expects the steps in the route to transform order.fromToken to order.toToken
    /// @dev Expects at least order.minToTokenAmount to be transferred to the recipient
    function _executeOrder(Order calldata order, Step[] calldata route, address recipient, uint256 feeBps) private {
        widoTokenManager.pullTokens(order.user, order.inputs);

        for (uint256 i = 0; i < order.inputs.length; ) {
            IWidoRouter.OrderInput calldata input = order.inputs[i];

            uint256 balance;
            if (input.tokenAddress == address(0)) {
                balance = address(this).balance;
            } else {
                balance = ERC20(input.tokenAddress).balanceOf(address(this));
            }
            require(balance >= input.amount, "Balance lower than order amount");
            _collectFees(input.tokenAddress, balance, feeBps);

            unchecked {
                i++;
            }
        }

        _executeSteps(route);

        for (uint256 i = 0; i < order.outputs.length; ) {
            IWidoRouter.OrderOutput calldata output = order.outputs[i];

            if (output.tokenAddress == address(0)) {
                uint256 balance = address(this).balance;
                if (balance < output.minOutputAmount) {
                    revert SlippageTooHigh(output.minOutputAmount, balance);
                }
                recipient.safeTransferETH(balance);
            } else {
                uint256 balance = ERC20(output.tokenAddress).balanceOf(address(this));
                if (balance < output.minOutputAmount) {
                    revert SlippageTooHigh(output.minOutputAmount, balance);
                }
                ERC20(output.tokenAddress).safeTransfer(recipient, balance);
            }

            unchecked {
                i++;
            }
        }
    }

    /// @notice Returns the amount of tokens or native tokens after accounting for fee
    /// @param fromToken Address of the token for the fee
    /// @param amount Amount of tokens to subtract the fee
    /// @param feeBps Fee in basis points (bps)
    /// @dev Sends the fee to the bank to not maintain any balance in the contract
    function _collectFees(address fromToken, uint256 amount, uint256 feeBps) private {
        require(feeBps <= 100, "Fee out of range");
        uint256 fee = (amount * feeBps) / 10000;
        if (fee > 0) {
            if (fromToken == address(0)) {
                bank.safeTransferETH(fee);
            } else {
                ERC20(fromToken).safeTransfer(bank, fee);
            }
        }
    }

    /// @notice Executes order to transform ERC20 token from order.fromToken to order.toToken
    /// @param order Order describing the expectation of the token transformation
    /// @param route Route describes the details of the token transformation
    /// @param feeBps Fee in basis points (bps)
    /// @param partner Partner address
    function executeOrder(
        Order calldata order,
        Step[] calldata route,
        uint256 feeBps,
        address partner
    ) external payable override nonReentrant {
        require(msg.sender == order.user, "Invalid order user");
        _executeOrder(order, route, order.user, feeBps);
        emit FulfilledOrder(order, msg.sender, order.user, feeBps, partner);
    }

    /// @notice Executes order to transform ERC20 token from order.fromToken to order.toToken
    /// @param order Order describing the expectation of the token transformation
    /// @param route Route describes the details of the token transformation
    /// @param recipient Destination address where the final tokens are sent
    /// @param feeBps Fee in basis points (bps)
    /// @param partner Partner address
    function executeOrder(
        Order calldata order,
        Step[] calldata route,
        address recipient,
        uint256 feeBps,
        address partner
    ) external payable override nonReentrant {
        require(msg.sender == order.user, "Invalid order user");
        _executeOrder(order, route, recipient, feeBps);
        emit FulfilledOrder(order, msg.sender, recipient, feeBps, partner);
    }

    /// @notice Executes the order with valid EIP-712 signature
    /// @param order Order describing the expectation of the token transformation
    /// @param route Expects a valid route to transform order.fromToken to order.toToken
    /// @param v v of the signature
    /// @param r r of the signature
    /// @param s s of the signation
    /// @param feeBps Fee in basis points (bps)
    /// @param partner Partner address
    function executeOrderWithSignature(
        Order calldata order,
        Step[] calldata route,
        uint8 v,
        bytes32 r,
        bytes32 s,
        uint256 feeBps,
        address partner
    ) external override nonReentrant {
        require(verifyOrder(order, v, r, s), "Invalid order");
        nonces[order.user]++;
        _executeOrder(order, route, order.user, feeBps);
        emit FulfilledOrder(order, msg.sender, order.user, feeBps, partner);
    }

    /// @notice Allow receiving of native tokens
    receive() external payable {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 11 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @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 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;

    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() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.7;

interface IWidoRouter {
    /// @notice OrderInput object describing the desired token inputs
    /// @param tokenAddress Address of the input token
    /// @param fromTokenAmount Amount of the input token to spend on the user's behalf
    /// @dev amount must == msg.value when token == address(0)
    struct OrderInput {
        address tokenAddress;
        uint256 amount;
    }

    /// @notice OrderOutput object describing the desired token outputs
    /// @param tokenAddress Address of the output token
    /// @param minOutputAmount Minimum amount of the output token the user is willing to accept for this order
    struct OrderOutput {
        address tokenAddress;
        uint256 minOutputAmount;
    }

    /// @notice Order object describing the requirements of the zap
    /// @param inputs Array of input objects, see OrderInput
    /// @param outputs Array of output objects, see OrderOutput
    /// @param user Address of user placing the order
    /// @param nonce Number used once to ensure an order requested by a signature only executes once
    /// @param expiration Timestamp until which the order is valid to execute
    struct Order {
        OrderInput[] inputs;
        OrderOutput[] outputs;
        address user;
        uint32 nonce;
        uint32 expiration;
    }

    /// @notice Step object describing a single token transformation
    /// @param fromToken Address of the from token
    /// @param targetAddress Address of the contract performing the transformation
    /// @param data Data which the swap contract will be called with
    /// @param amountIndex Index for the from token amount that can be found in data and needs to be updated with the most recent value.
    struct Step {
        address fromToken;
        address targetAddress;
        bytes data;
        int32 amountIndex;
    }

    function verifyOrder(Order calldata order, uint8 v, bytes32 r, bytes32 s) external view returns (bool);

    function executeOrder(
        Order calldata order,
        Step[] calldata route,
        uint256 feeBps,
        address partner
    ) external payable;

    function executeOrder(
        Order calldata order,
        Step[] calldata route,
        address recipient,
        uint256 feeBps,
        address partner
    ) external payable;

    function executeOrderWithSignature(
        Order calldata order,
        Step[] calldata route,
        uint8 v,
        bytes32 r,
        bytes32 s,
        uint256 feeBps,
        address partner
    ) external;
}

// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.7;
import "./IWidoRouter.sol";

interface IWidoTokenManager {
    function pullTokens(address user, IWidoRouter.OrderInput[] calldata inputs) external;
}

// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.7;

import "solmate/src/utils/SafeTransferLib.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IWidoTokenManager.sol";

contract WidoTokenManager is IWidoTokenManager, Ownable {
    using SafeTransferLib for ERC20;

    /// @notice Transfers tokens or native tokens from the user
    /// @param user The address of the order user
    /// @param inputs Array of input objects, see OrderInput and Order
    function pullTokens(address user, IWidoRouter.OrderInput[] calldata inputs) external override onlyOwner {
        for (uint256 i = 0; i < inputs.length; i++) {
            IWidoRouter.OrderInput calldata input = inputs[i];

            if (input.tokenAddress == address(0)) {
                continue;
            }

            ERC20(input.tokenAddress).safeTransferFrom(user, owner(), input.amount);
        }
    }
}

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

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

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

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
            mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 2000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_wrappedNativeToken","type":"address"},{"internalType":"address","name":"_bank","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"expectedAmount","type":"uint256"},{"internalType":"uint256","name":"actualAmount","type":"uint256"}],"name":"SlippageTooHigh","type":"error"},{"anonymous":false,"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderInput[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderOutput[]","name":"outputs","type":"tuple[]"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint32","name":"expiration","type":"uint32"}],"indexed":false,"internalType":"struct IWidoRouter.Order","name":"order","type":"tuple"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeBps","type":"uint256"},{"indexed":true,"internalType":"address","name":"partner","type":"address"}],"name":"FulfilledOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"bank","type":"address"}],"name":"SetBank","type":"event"},{"inputs":[],"name":"bank","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderInput[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderOutput[]","name":"outputs","type":"tuple[]"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint32","name":"expiration","type":"uint32"}],"internalType":"struct IWidoRouter.Order","name":"order","type":"tuple"},{"components":[{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"address","name":"targetAddress","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"int32","name":"amountIndex","type":"int32"}],"internalType":"struct IWidoRouter.Step[]","name":"route","type":"tuple[]"},{"internalType":"uint256","name":"feeBps","type":"uint256"},{"internalType":"address","name":"partner","type":"address"}],"name":"executeOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderInput[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderOutput[]","name":"outputs","type":"tuple[]"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint32","name":"expiration","type":"uint32"}],"internalType":"struct IWidoRouter.Order","name":"order","type":"tuple"},{"components":[{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"address","name":"targetAddress","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"int32","name":"amountIndex","type":"int32"}],"internalType":"struct IWidoRouter.Step[]","name":"route","type":"tuple[]"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"feeBps","type":"uint256"},{"internalType":"address","name":"partner","type":"address"}],"name":"executeOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderInput[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderOutput[]","name":"outputs","type":"tuple[]"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint32","name":"expiration","type":"uint32"}],"internalType":"struct IWidoRouter.Order","name":"order","type":"tuple"},{"components":[{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"address","name":"targetAddress","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"int32","name":"amountIndex","type":"int32"}],"internalType":"struct IWidoRouter.Step[]","name":"route","type":"tuple[]"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"feeBps","type":"uint256"},{"internalType":"address","name":"partner","type":"address"}],"name":"executeOrderWithSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bank","type":"address"}],"name":"setBank","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderInput[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"}],"internalType":"struct IWidoRouter.OrderOutput[]","name":"outputs","type":"tuple[]"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint32","name":"expiration","type":"uint32"}],"internalType":"struct IWidoRouter.Order","name":"order","type":"tuple"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"verifyOrder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"widoTokenManager","outputs":[{"internalType":"contract WidoTokenManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wrappedNativeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c06040523480156200001157600080fd5b5060405162003189380380620031898339810160408190526200003491620001a2565b6200003f3362000127565b600180556001600160a01b038216158015906200006457506001600160a01b03811615155b620000b55760405162461bcd60e51b815260206004820181905260248201527f4164647265737365732063616e6e6f74206265207a65726f2061646472657373604482015260640160405180910390fd5b606082901b6001600160601b031916608052600380546001600160a01b0319166001600160a01b038316179055604051620000f09062000177565b604051809103906000f0801580156200010d573d6000803e3d6000fd5b5060601b6001600160601b03191660a05250620001da9050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6105cd8062002bbc83390190565b80516001600160a01b03811681146200019d57600080fd5b919050565b60008060408385031215620001b657600080fd5b620001c18362000185565b9150620001d16020840162000185565b90509250929050565b60805160601c60a05160601c6129a8620002146000396000818161015c01528181610e9e01526118c00152600061010b01526129a86000f3fe6080604052600436106100cb5760003560e01c80637ecebe0011610074578063e58610841161004e578063e58610841461024f578063f2fde38b1461026f578063fc171d911461028f57600080fd5b80637ecebe00146101e35780638da5cb5b1461021e578063916a3bd91461023c57600080fd5b80633967048b116100a55780633967048b1461017e578063715018a6146101ae57806376cdb03b146101c357600080fd5b8063090d23b9146100d757806317fcb39b146100f95780631802553e1461014a57600080fd5b366100d257005b600080fd5b3480156100e357600080fd5b506100f76100f2366004612025565b6102a2565b005b34801561010557600080fd5b5061012d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561015657600080fd5b5061012d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561018a57600080fd5b5061019e6101993660046122be565b6103ae565b6040519015158152602001610141565b3480156101ba57600080fd5b506100f761076b565b3480156101cf57600080fd5b5060035461012d906001600160a01b031681565b3480156101ef57600080fd5b506102106101fe366004612025565b60026020526000908152604090205481565b604051908152602001610141565b34801561022a57600080fd5b506000546001600160a01b031661012d565b6100f761024a366004612192565b61077f565b34801561025b57600080fd5b506100f761026a366004612216565b6108c3565b34801561027b57600080fd5b506100f761028a366004612025565b610a2d565b6100f761029d3660046120fe565b610abd565b6102aa610bed565b6001600160a01b038116158015906102cb57506001600160a01b0381163014155b6103425760405162461bcd60e51b815260206004820152603a60248201527f42616e6b20616464726573732063616e6e6f74206265207a65726f206164647260448201527f657373206f72205769646f20526f75746572206164647265737300000000000060648201526084015b60405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f10f5824683d64a0712038f2244e046b174a1cc57fbb8556bfda5ffb2612440679060200160405180910390a150565b600080604051602001610430907f454950373132446f6d61696e28737472696e67206e616d652c737472696e672081527f76657273696f6e2c75696e7432353620636861696e49642c616464726573732060208201527f766572696679696e67436f6e7472616374290000000000000000000000000000604082015260520190565b60408051601f198184030181528282528051602091820120908301527fe18799aceb0d5c1134b671173b8112a3ebcbe15aaef1b5bf23f47082a09df0ec908201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c001604051602081830303815290604052805190602001209050600061052d826104d6896104d1906127cf565b610c47565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810192909252604282015260620160405160208183030381529060405280519060200120878787610e04565b90506001600160a01b0381161580159061056757506001600160a01b03811661055c6060890160408a01612025565b6001600160a01b0316145b6105b35760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e61747572650000000000000000000000000000006044820152606401610339565b600260006105c760608a0160408b01612025565b6001600160a01b031681526020810191909152604001600020546105f16080890160608a01612334565b63ffffffff16146106445760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964206e6f6e6365000000000000000000000000000000000000006044820152606401610339565b61065460a0880160808901612334565b63ffffffff16158061067b575061067160a0880160808901612334565b63ffffffff164211155b6106c75760405162461bcd60e51b815260206004820152600f60248201527f45787069726564207265717565737400000000000000000000000000000000006044820152606401610339565b60005b6106d488806125c0565b905081101561075d57366106e889806125c0565b838181106106f8576106f8612946565b905060400201905060008160200135116107545760405162461bcd60e51b815260206004820152601f60248201527f416d6f756e742073686f756c642062652067726561746572207468616e2030006044820152606401610339565b506001016106ca565b506001979650505050505050565b610773610bed565b61077d6000610e2c565b565b600260015414156107d25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610339565b60026001556107e76060860160408701612025565b6001600160a01b0316336001600160a01b0316146108475760405162461bcd60e51b815260206004820152601260248201527f496e76616c6964206f72646572207573657200000000000000000000000000006044820152606401610339565b61086385858561085d6060840160408501612025565b86610e94565b6001600160a01b038116337f1ac24a2fc0a341cfcb02105ee08de6110d72cdf0d2b78fe9136f5da301eb9091876108a06060820160408301612025565b866040516108b0939291906124b8565b60405180910390a3505060018055505050565b600260015414156109165760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610339565b6002600155610927888686866103ae565b6109735760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964206f72646572000000000000000000000000000000000000006044820152606401610339565b6002600061098760608b0160408c01612025565b6001600160a01b03168152602081019190915260400160009081208054916109ae836128ff565b909155506109ca905088888861085d6060840160408501612025565b6001600160a01b038116337f1ac24a2fc0a341cfcb02105ee08de6110d72cdf0d2b78fe9136f5da301eb90918a610a076060820160408301612025565b86604051610a17939291906124b8565b60405180910390a3505060018055505050505050565b610a35610bed565b6001600160a01b038116610ab15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610339565b610aba81610e2c565b50565b60026001541415610b105760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610339565b6002600155610b256060870160408801612025565b6001600160a01b0316336001600160a01b031614610b855760405162461bcd60e51b815260206004820152601260248201527f496e76616c6964206f72646572207573657200000000000000000000000000006044820152606401610339565b610b928686868686610e94565b806001600160a01b0316336001600160a01b03167f1ac24a2fc0a341cfcb02105ee08de6110d72cdf0d2b78fe9136f5da301eb9091888686604051610bd9939291906124b8565b60405180910390a350506001805550505050565b6000546001600160a01b0316331461077d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610339565b6000604051602001610d60907f4f72646572284f72646572496e7075745b5d20696e707574732c4f726465724f81527f75747075745b5d206f7574707574732c6164647265737320757365722c75696e60208201527f743332206e6f6e63652c75696e7433322065787069726174696f6e294f72646560408201527f72496e707574286164647265737320746f6b656e416464726573732c75696e7460608201527f32353620616d6f756e74294f726465724f75747075742861646472657373207460808201527f6f6b656e416464726573732c75696e74323536206d696e4f7574707574416d6f60a08201527f756e74290000000000000000000000000000000000000000000000000000000060c082015260c40190565b60405160208183030381529060405280519060200120610d838360000151611267565b610d9084602001516113c1565b604080860151606087015160808801519251610de79695949390602001958652602086019490945260408501929092526001600160a01b0316606084015263ffffffff90811660808401521660a082015260c00190565b604051602081830303815290604052805190602001209050919050565b6000806000610e15878787876114eb565b91509150610e22816115d8565b5095945050505050565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166377fc3fa8610ed36060880160408901612025565b610edd88806125c0565b6040518463ffffffff1660e01b8152600401610efb93929190612432565b600060405180830381600087803b158015610f1557600080fd5b505af1158015610f29573d6000803e3d6000fd5b5050505060005b610f3a86806125c0565b905081101561108d5736610f4e87806125c0565b83818110610f5e57610f5e612946565b6040029190910191506000905080610f796020840184612025565b6001600160a01b03161415610f8f575047611018565b610f9c6020830183612025565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610fdd57600080fd5b505afa158015610ff1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611015919061231b565b90505b816020013581101561106c5760405162461bcd60e51b815260206004820152601f60248201527f42616c616e6365206c6f776572207468616e206f7264657220616d6f756e74006044820152606401610339565b61108361107c6020840184612025565b82866117c9565b5050600101610f30565b506110988484611884565b60005b6110a860208701876125c0565b905081101561125f57366110bf60208801886125c0565b838181106110cf576110cf612946565b604002919091019150600090506110e96020830183612025565b6001600160a01b0316141561115d57476020820135811015611144576040517f76baadda0000000000000000000000000000000000000000000000000000000081526020830135600482015260248101829052604401610339565b6111576001600160a01b03861682611c60565b50611256565b600061116c6020830183612025565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b1580156111ad57600080fd5b505afa1580156111c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e5919061231b565b90508160200135811015611232576040517f76baadda0000000000000000000000000000000000000000000000000000000081526020830135600482015260248101829052604401610339565b61125485826112446020860186612025565b6001600160a01b03169190611cbb565b505b5060010161109b565b505050505050565b600080825167ffffffffffffffff8111156112845761128461295c565b6040519080825280602002602001820160405280156112ad578160200160208202803683370190505b50905060005b835181101561139157604051602001611315907f4f72646572496e707574286164647265737320746f6b656e416464726573732c81527f75696e7432353620616d6f756e742900000000000000000000000000000000006020820152602f0190565b6040516020818303038152906040528051906020012084828151811061133d5761133d612946565b602002602001015160405160200161135692919061245e565b6040516020818303038152906040528051906020012082828151811061137e5761137e612946565b60209081029190910101526001016112b3565b50806040516020016113a391906123ac565b60405160208183030381529060405280519060200120915050919050565b600080825167ffffffffffffffff8111156113de576113de61295c565b604051908082528060200260200182016040528015611407578160200160208202803683370190505b50905060005b83518110156113915760405160200161146f907f4f726465724f7574707574286164647265737320746f6b656e4164647265737381527f2c75696e74323536206d696e4f7574707574416d6f756e742900000000000000602082015260390190565b6040516020818303038152906040528051906020012084828151811061149757611497612946565b60200260200101516040516020016114b092919061245e565b604051602081830303815290604052805190602001208282815181106114d8576114d8612946565b602090810291909101015260010161140d565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561152257506000905060036115cf565b8460ff16601b1415801561153a57508460ff16601c14155b1561154b57506000905060046115cf565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561159f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166115c8576000600192509250506115cf565b9150600090505b94509492505050565b60008160048111156115ec576115ec612930565b14156115f55750565b600181600481111561160957611609612930565b14156116575760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610339565b600281600481111561166b5761166b612930565b14156116b95760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610339565b60038160048111156116cd576116cd612930565b14156117415760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610339565b600481600481111561175557611755612930565b1415610aba5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610339565b606481111561181a5760405162461bcd60e51b815260206004820152601060248201527f466565206f7574206f662072616e6765000000000000000000000000000000006044820152606401610339565b600061271061182983856127b0565b611833919061278e565b9050801561187e576001600160a01b0384166118645760035461185f906001600160a01b031682611c60565b61187e565b60035461187e906001600160a01b03868116911683611cbb565b50505050565b60005b81811015611c5b57368383838181106118a2576118a2612946565b90506020028101906118b49190612651565b90506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166118f06040830160208401612025565b6001600160a01b0316141561196d5760405162461bcd60e51b815260206004820152602860248201527f5769646f3a20666f7262696464656e2063616c6c20746f205769646f546f6b6560448201527f6e4d616e616765720000000000000000000000000000000000000000000000006064820152608401610339565b6000808061197e6020850185612025565b6001600160a01b03161415611994575047611a95565b5060006119a46020840184612025565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b1580156119e557600080fd5b505afa1580156119f9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1d919061231b565b915060008211611a6f5760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f7567682062616c616e636520666f72207468652073746570006044820152606401610339565b611a95611a7f6020850185612025565b611a8f6040860160208701612025565b84611d5a565b60606000611aa860808601868401612047565b60030b12611b4b576000611ac26080860160608701612047565b60030b9050611ad4604086018661260a565b611ae291839160009161274c565b60408051602081018890520160408051601f19818403018152918152611b0a9089018961260a565b611b15866020612776565b611b2092829061274c565b604051602001611b349594939291906123e2565b604051602081830303815290604052915050611b90565b611b58604085018561260a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b600080611ba36040870160208801612025565b6001600160a01b03168484604051611bbb9190612416565b60006040518083038185875af1925050503d8060008114611bf8576040519150601f19603f3d011682016040523d82523d6000602084013e611bfd565b606091505b509150915081611c4957604481511015611c1657600080fd5b60048101905080806020019051810190611c30919061206a565b60405162461bcd60e51b81526004016103399190612485565b50506001909401935061188792505050565b505050565b600080600080600085875af1905080611c5b5760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610339565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061187e5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610339565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301528491839183169063dd62ed3e9060440160206040518083038186803b158015611dbe57600080fd5b505afa158015611dd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df6919061231b565b101561187e5761187e6001600160a01b0382168460001960006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061187e5760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610339565b80356001600160a01b0381168114611ec357600080fd5b919050565b600082601f830112611ed957600080fd5b81356020611eee611ee9836126df565b6126ae565b80838252828201915082860187848660061b8901011115611f0e57600080fd5b60005b85811015611f3857611f238983611f91565b84529284019260409190910190600101611f11565b5090979650505050505050565b60008083601f840112611f5757600080fd5b50813567ffffffffffffffff811115611f6f57600080fd5b6020830191508360208260051b8501011115611f8a57600080fd5b9250929050565b600060408284031215611fa357600080fd5b6040516040810181811067ffffffffffffffff82111715611fc657611fc661295c565b604052905080611fd583611eac565b8152602083013560208201525092915050565b600060a08284031215611ffa57600080fd5b50919050565b803563ffffffff81168114611ec357600080fd5b803560ff81168114611ec357600080fd5b60006020828403121561203757600080fd5b61204082611eac565b9392505050565b60006020828403121561205957600080fd5b81358060030b811461204057600080fd5b60006020828403121561207c57600080fd5b815167ffffffffffffffff8082111561209457600080fd5b818401915084601f8301126120a857600080fd5b8151818111156120ba576120ba61295c565b6120cd6020601f19601f840116016126ae565b91508082528560208285010111156120e457600080fd5b6120f58160208401602086016128d3565b50949350505050565b60008060008060008060a0878903121561211757600080fd5b863567ffffffffffffffff8082111561212f57600080fd5b61213b8a838b01611fe8565b9750602089013591508082111561215157600080fd5b5061215e89828a01611f45565b9096509450612171905060408801611eac565b92506060870135915061218660808801611eac565b90509295509295509295565b6000806000806000608086880312156121aa57600080fd5b853567ffffffffffffffff808211156121c257600080fd5b6121ce89838a01611fe8565b965060208801359150808211156121e457600080fd5b506121f188828901611f45565b9095509350506040860135915061220a60608701611eac565b90509295509295909350565b60008060008060008060008060e0898b03121561223257600080fd5b883567ffffffffffffffff8082111561224a57600080fd5b6122568c838d01611fe8565b995060208b013591508082111561226c57600080fd5b506122798b828c01611f45565b909850965061228c905060408a01612014565b9450606089013593506080890135925060a089013591506122af60c08a01611eac565b90509295985092959890939650565b600080600080608085870312156122d457600080fd5b843567ffffffffffffffff8111156122eb57600080fd5b6122f787828801611fe8565b94505061230660208601612014565b93969395505050506040820135916060013590565b60006020828403121561232d57600080fd5b5051919050565b60006020828403121561234657600080fd5b61204082612000565b81835260208301925060008160005b8481101561238357612370868361238d565b604095860195919091019060010161235e565b5093949350505050565b6001600160a01b0361239e82611eac565b168252602090810135910152565b815160009082906020808601845b838110156123d6578151855293820193908201906001016123ba565b50929695505050505050565b8486823760008582016000815285516123ff818360208a016128d3565b018385823760009301928352509095945050505050565b600082516124288184602087016128d3565b9190910192915050565b6001600160a01b038416815260406020820152600061245560408301848661234f565b95945050505050565b82815260608101612040602083018480516001600160a01b03168252602090810151910152565b60208152600082518060208401526124a48160408501602087016128d3565b601f01601f19169190910160400192915050565b6060815260006124c88586612703565b60a060608501526124de6101008501828461234f565b9150506124ee6020870187612703565b8483037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa00160808601528083529091600091906020015b8183101561254a57612537818561238d565b6040938401936001939093019201612525565b61255660408a01611eac565b6001600160a01b03811660a0880152935061257360608a01612000565b63ffffffff811660c0880152935061258d60808a01612000565b63ffffffff1660e08701526001600160a01b038816602087015293506125b292505050565b826040830152949350505050565b6000808335601e198436030181126125d757600080fd5b83018035915067ffffffffffffffff8211156125f257600080fd5b6020019150600681901b3603821315611f8a57600080fd5b6000808335601e1984360301811261262157600080fd5b83018035915067ffffffffffffffff82111561263c57600080fd5b602001915036819003821315611f8a57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261242857600080fd5b60405160a0810167ffffffffffffffff811182821017156126a8576126a861295c565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156126d7576126d761295c565b604052919050565b600067ffffffffffffffff8211156126f9576126f961295c565b5060051b60200190565b6000808335601e1984360301811261271a57600080fd5b830160208101925035905067ffffffffffffffff81111561273a57600080fd5b8060061b3603831315611f8a57600080fd5b6000808585111561275c57600080fd5b8386111561276957600080fd5b5050820193919092039150565b600082198211156127895761278961291a565b500190565b6000826127ab57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156127ca576127ca61291a565b500290565b600060a082360312156127e157600080fd5b6127e9612685565b823567ffffffffffffffff8082111561280157600080fd5b9084019036601f83011261281457600080fd5b81356020612824611ee9836126df565b8281528181019085830136600686901b88018501111561284357600080fd5b600096505b8487101561286f5761285a3682611f91565b83526001969096019591830191604001612848565b508652508681013593508284111561288657600080fd5b61289236858901611ec8565b81860152505050506128a660408401611eac565b60408201526128b760608401612000565b60608201526128c860808401612000565b608082015292915050565b60005b838110156128ee5781810151838201526020016128d6565b8381111561187e5750506000910152565b60006000198214156129135761291361291a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea264697066735822122050ff5cabe47edd9569ce89e0ba0f68eff813e85d665e712a723440f1d6f5cc4564736f6c63430008070033608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61054f8061007e6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063715018a61461005157806377fc3fa81461005b5780638da5cb5b1461006e578063f2fde38b1461009a575b600080fd5b6100596100ad565b005b610059610069366004610404565b6100c1565b6000546040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100596100a83660046103e2565b61018f565b6100b5610231565b6100bf6000610298565b565b6100c9610231565b60005b8181101561018957368383838181106100e7576100e76104ea565b6040029190910191506000905061010160208301836103e2565b73ffffffffffffffffffffffffffffffffffffffff1614156101235750610177565b6101758561014660005473ffffffffffffffffffffffffffffffffffffffff1690565b6020840180359061015790866103e2565b73ffffffffffffffffffffffffffffffffffffffff1692919061030d565b505b806101818161048a565b9150506100cc565b50505050565b610197610231565b73ffffffffffffffffffffffffffffffffffffffff81166102255760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61022e81610298565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146100bf5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161021c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806103b25760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640161021c565b5050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146103dd57600080fd5b919050565b6000602082840312156103f457600080fd5b6103fd826103b9565b9392505050565b60008060006040848603121561041957600080fd5b610422846103b9565b9250602084013567ffffffffffffffff8082111561043f57600080fd5b818601915086601f83011261045357600080fd5b81358181111561046257600080fd5b8760208260061b850101111561047757600080fd5b6020830194508093505050509250925092565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156104e3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea26469706673582212204dd1f47161d778557eea8c911bac4fd310ad7cc96f57ff7b36fb2fe38010b82464736f6c6343000807003300000000000000000000000042000000000000000000000000000000000000060000000000000000000000005ef7f250f74d4f11a68054ae4e150705474a6d4a

Deployed Bytecode

0x6080604052600436106100cb5760003560e01c80637ecebe0011610074578063e58610841161004e578063e58610841461024f578063f2fde38b1461026f578063fc171d911461028f57600080fd5b80637ecebe00146101e35780638da5cb5b1461021e578063916a3bd91461023c57600080fd5b80633967048b116100a55780633967048b1461017e578063715018a6146101ae57806376cdb03b146101c357600080fd5b8063090d23b9146100d757806317fcb39b146100f95780631802553e1461014a57600080fd5b366100d257005b600080fd5b3480156100e357600080fd5b506100f76100f2366004612025565b6102a2565b005b34801561010557600080fd5b5061012d7f000000000000000000000000420000000000000000000000000000000000000681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561015657600080fd5b5061012d7f000000000000000000000000c1ae663b4b4d211b4f865dc36a0db36ffcf7152881565b34801561018a57600080fd5b5061019e6101993660046122be565b6103ae565b6040519015158152602001610141565b3480156101ba57600080fd5b506100f761076b565b3480156101cf57600080fd5b5060035461012d906001600160a01b031681565b3480156101ef57600080fd5b506102106101fe366004612025565b60026020526000908152604090205481565b604051908152602001610141565b34801561022a57600080fd5b506000546001600160a01b031661012d565b6100f761024a366004612192565b61077f565b34801561025b57600080fd5b506100f761026a366004612216565b6108c3565b34801561027b57600080fd5b506100f761028a366004612025565b610a2d565b6100f761029d3660046120fe565b610abd565b6102aa610bed565b6001600160a01b038116158015906102cb57506001600160a01b0381163014155b6103425760405162461bcd60e51b815260206004820152603a60248201527f42616e6b20616464726573732063616e6e6f74206265207a65726f206164647260448201527f657373206f72205769646f20526f75746572206164647265737300000000000060648201526084015b60405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f10f5824683d64a0712038f2244e046b174a1cc57fbb8556bfda5ffb2612440679060200160405180910390a150565b600080604051602001610430907f454950373132446f6d61696e28737472696e67206e616d652c737472696e672081527f76657273696f6e2c75696e7432353620636861696e49642c616464726573732060208201527f766572696679696e67436f6e7472616374290000000000000000000000000000604082015260520190565b60408051601f198184030181528282528051602091820120908301527fe18799aceb0d5c1134b671173b8112a3ebcbe15aaef1b5bf23f47082a09df0ec908201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c001604051602081830303815290604052805190602001209050600061052d826104d6896104d1906127cf565b610c47565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810192909252604282015260620160405160208183030381529060405280519060200120878787610e04565b90506001600160a01b0381161580159061056757506001600160a01b03811661055c6060890160408a01612025565b6001600160a01b0316145b6105b35760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e61747572650000000000000000000000000000006044820152606401610339565b600260006105c760608a0160408b01612025565b6001600160a01b031681526020810191909152604001600020546105f16080890160608a01612334565b63ffffffff16146106445760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964206e6f6e6365000000000000000000000000000000000000006044820152606401610339565b61065460a0880160808901612334565b63ffffffff16158061067b575061067160a0880160808901612334565b63ffffffff164211155b6106c75760405162461bcd60e51b815260206004820152600f60248201527f45787069726564207265717565737400000000000000000000000000000000006044820152606401610339565b60005b6106d488806125c0565b905081101561075d57366106e889806125c0565b838181106106f8576106f8612946565b905060400201905060008160200135116107545760405162461bcd60e51b815260206004820152601f60248201527f416d6f756e742073686f756c642062652067726561746572207468616e2030006044820152606401610339565b506001016106ca565b506001979650505050505050565b610773610bed565b61077d6000610e2c565b565b600260015414156107d25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610339565b60026001556107e76060860160408701612025565b6001600160a01b0316336001600160a01b0316146108475760405162461bcd60e51b815260206004820152601260248201527f496e76616c6964206f72646572207573657200000000000000000000000000006044820152606401610339565b61086385858561085d6060840160408501612025565b86610e94565b6001600160a01b038116337f1ac24a2fc0a341cfcb02105ee08de6110d72cdf0d2b78fe9136f5da301eb9091876108a06060820160408301612025565b866040516108b0939291906124b8565b60405180910390a3505060018055505050565b600260015414156109165760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610339565b6002600155610927888686866103ae565b6109735760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964206f72646572000000000000000000000000000000000000006044820152606401610339565b6002600061098760608b0160408c01612025565b6001600160a01b03168152602081019190915260400160009081208054916109ae836128ff565b909155506109ca905088888861085d6060840160408501612025565b6001600160a01b038116337f1ac24a2fc0a341cfcb02105ee08de6110d72cdf0d2b78fe9136f5da301eb90918a610a076060820160408301612025565b86604051610a17939291906124b8565b60405180910390a3505060018055505050505050565b610a35610bed565b6001600160a01b038116610ab15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610339565b610aba81610e2c565b50565b60026001541415610b105760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610339565b6002600155610b256060870160408801612025565b6001600160a01b0316336001600160a01b031614610b855760405162461bcd60e51b815260206004820152601260248201527f496e76616c6964206f72646572207573657200000000000000000000000000006044820152606401610339565b610b928686868686610e94565b806001600160a01b0316336001600160a01b03167f1ac24a2fc0a341cfcb02105ee08de6110d72cdf0d2b78fe9136f5da301eb9091888686604051610bd9939291906124b8565b60405180910390a350506001805550505050565b6000546001600160a01b0316331461077d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610339565b6000604051602001610d60907f4f72646572284f72646572496e7075745b5d20696e707574732c4f726465724f81527f75747075745b5d206f7574707574732c6164647265737320757365722c75696e60208201527f743332206e6f6e63652c75696e7433322065787069726174696f6e294f72646560408201527f72496e707574286164647265737320746f6b656e416464726573732c75696e7460608201527f32353620616d6f756e74294f726465724f75747075742861646472657373207460808201527f6f6b656e416464726573732c75696e74323536206d696e4f7574707574416d6f60a08201527f756e74290000000000000000000000000000000000000000000000000000000060c082015260c40190565b60405160208183030381529060405280519060200120610d838360000151611267565b610d9084602001516113c1565b604080860151606087015160808801519251610de79695949390602001958652602086019490945260408501929092526001600160a01b0316606084015263ffffffff90811660808401521660a082015260c00190565b604051602081830303815290604052805190602001209050919050565b6000806000610e15878787876114eb565b91509150610e22816115d8565b5095945050505050565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b037f000000000000000000000000c1ae663b4b4d211b4f865dc36a0db36ffcf71528166377fc3fa8610ed36060880160408901612025565b610edd88806125c0565b6040518463ffffffff1660e01b8152600401610efb93929190612432565b600060405180830381600087803b158015610f1557600080fd5b505af1158015610f29573d6000803e3d6000fd5b5050505060005b610f3a86806125c0565b905081101561108d5736610f4e87806125c0565b83818110610f5e57610f5e612946565b6040029190910191506000905080610f796020840184612025565b6001600160a01b03161415610f8f575047611018565b610f9c6020830183612025565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610fdd57600080fd5b505afa158015610ff1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611015919061231b565b90505b816020013581101561106c5760405162461bcd60e51b815260206004820152601f60248201527f42616c616e6365206c6f776572207468616e206f7264657220616d6f756e74006044820152606401610339565b61108361107c6020840184612025565b82866117c9565b5050600101610f30565b506110988484611884565b60005b6110a860208701876125c0565b905081101561125f57366110bf60208801886125c0565b838181106110cf576110cf612946565b604002919091019150600090506110e96020830183612025565b6001600160a01b0316141561115d57476020820135811015611144576040517f76baadda0000000000000000000000000000000000000000000000000000000081526020830135600482015260248101829052604401610339565b6111576001600160a01b03861682611c60565b50611256565b600061116c6020830183612025565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b1580156111ad57600080fd5b505afa1580156111c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e5919061231b565b90508160200135811015611232576040517f76baadda0000000000000000000000000000000000000000000000000000000081526020830135600482015260248101829052604401610339565b61125485826112446020860186612025565b6001600160a01b03169190611cbb565b505b5060010161109b565b505050505050565b600080825167ffffffffffffffff8111156112845761128461295c565b6040519080825280602002602001820160405280156112ad578160200160208202803683370190505b50905060005b835181101561139157604051602001611315907f4f72646572496e707574286164647265737320746f6b656e416464726573732c81527f75696e7432353620616d6f756e742900000000000000000000000000000000006020820152602f0190565b6040516020818303038152906040528051906020012084828151811061133d5761133d612946565b602002602001015160405160200161135692919061245e565b6040516020818303038152906040528051906020012082828151811061137e5761137e612946565b60209081029190910101526001016112b3565b50806040516020016113a391906123ac565b60405160208183030381529060405280519060200120915050919050565b600080825167ffffffffffffffff8111156113de576113de61295c565b604051908082528060200260200182016040528015611407578160200160208202803683370190505b50905060005b83518110156113915760405160200161146f907f4f726465724f7574707574286164647265737320746f6b656e4164647265737381527f2c75696e74323536206d696e4f7574707574416d6f756e742900000000000000602082015260390190565b6040516020818303038152906040528051906020012084828151811061149757611497612946565b60200260200101516040516020016114b092919061245e565b604051602081830303815290604052805190602001208282815181106114d8576114d8612946565b602090810291909101015260010161140d565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561152257506000905060036115cf565b8460ff16601b1415801561153a57508460ff16601c14155b1561154b57506000905060046115cf565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561159f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166115c8576000600192509250506115cf565b9150600090505b94509492505050565b60008160048111156115ec576115ec612930565b14156115f55750565b600181600481111561160957611609612930565b14156116575760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610339565b600281600481111561166b5761166b612930565b14156116b95760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610339565b60038160048111156116cd576116cd612930565b14156117415760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610339565b600481600481111561175557611755612930565b1415610aba5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610339565b606481111561181a5760405162461bcd60e51b815260206004820152601060248201527f466565206f7574206f662072616e6765000000000000000000000000000000006044820152606401610339565b600061271061182983856127b0565b611833919061278e565b9050801561187e576001600160a01b0384166118645760035461185f906001600160a01b031682611c60565b61187e565b60035461187e906001600160a01b03868116911683611cbb565b50505050565b60005b81811015611c5b57368383838181106118a2576118a2612946565b90506020028101906118b49190612651565b90506001600160a01b037f000000000000000000000000c1ae663b4b4d211b4f865dc36a0db36ffcf71528166118f06040830160208401612025565b6001600160a01b0316141561196d5760405162461bcd60e51b815260206004820152602860248201527f5769646f3a20666f7262696464656e2063616c6c20746f205769646f546f6b6560448201527f6e4d616e616765720000000000000000000000000000000000000000000000006064820152608401610339565b6000808061197e6020850185612025565b6001600160a01b03161415611994575047611a95565b5060006119a46020840184612025565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b1580156119e557600080fd5b505afa1580156119f9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1d919061231b565b915060008211611a6f5760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f7567682062616c616e636520666f72207468652073746570006044820152606401610339565b611a95611a7f6020850185612025565b611a8f6040860160208701612025565b84611d5a565b60606000611aa860808601868401612047565b60030b12611b4b576000611ac26080860160608701612047565b60030b9050611ad4604086018661260a565b611ae291839160009161274c565b60408051602081018890520160408051601f19818403018152918152611b0a9089018961260a565b611b15866020612776565b611b2092829061274c565b604051602001611b349594939291906123e2565b604051602081830303815290604052915050611b90565b611b58604085018561260a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b600080611ba36040870160208801612025565b6001600160a01b03168484604051611bbb9190612416565b60006040518083038185875af1925050503d8060008114611bf8576040519150601f19603f3d011682016040523d82523d6000602084013e611bfd565b606091505b509150915081611c4957604481511015611c1657600080fd5b60048101905080806020019051810190611c30919061206a565b60405162461bcd60e51b81526004016103399190612485565b50506001909401935061188792505050565b505050565b600080600080600085875af1905080611c5b5760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610339565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061187e5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610339565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301528491839183169063dd62ed3e9060440160206040518083038186803b158015611dbe57600080fd5b505afa158015611dd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df6919061231b565b101561187e5761187e6001600160a01b0382168460001960006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061187e5760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610339565b80356001600160a01b0381168114611ec357600080fd5b919050565b600082601f830112611ed957600080fd5b81356020611eee611ee9836126df565b6126ae565b80838252828201915082860187848660061b8901011115611f0e57600080fd5b60005b85811015611f3857611f238983611f91565b84529284019260409190910190600101611f11565b5090979650505050505050565b60008083601f840112611f5757600080fd5b50813567ffffffffffffffff811115611f6f57600080fd5b6020830191508360208260051b8501011115611f8a57600080fd5b9250929050565b600060408284031215611fa357600080fd5b6040516040810181811067ffffffffffffffff82111715611fc657611fc661295c565b604052905080611fd583611eac565b8152602083013560208201525092915050565b600060a08284031215611ffa57600080fd5b50919050565b803563ffffffff81168114611ec357600080fd5b803560ff81168114611ec357600080fd5b60006020828403121561203757600080fd5b61204082611eac565b9392505050565b60006020828403121561205957600080fd5b81358060030b811461204057600080fd5b60006020828403121561207c57600080fd5b815167ffffffffffffffff8082111561209457600080fd5b818401915084601f8301126120a857600080fd5b8151818111156120ba576120ba61295c565b6120cd6020601f19601f840116016126ae565b91508082528560208285010111156120e457600080fd5b6120f58160208401602086016128d3565b50949350505050565b60008060008060008060a0878903121561211757600080fd5b863567ffffffffffffffff8082111561212f57600080fd5b61213b8a838b01611fe8565b9750602089013591508082111561215157600080fd5b5061215e89828a01611f45565b9096509450612171905060408801611eac565b92506060870135915061218660808801611eac565b90509295509295509295565b6000806000806000608086880312156121aa57600080fd5b853567ffffffffffffffff808211156121c257600080fd5b6121ce89838a01611fe8565b965060208801359150808211156121e457600080fd5b506121f188828901611f45565b9095509350506040860135915061220a60608701611eac565b90509295509295909350565b60008060008060008060008060e0898b03121561223257600080fd5b883567ffffffffffffffff8082111561224a57600080fd5b6122568c838d01611fe8565b995060208b013591508082111561226c57600080fd5b506122798b828c01611f45565b909850965061228c905060408a01612014565b9450606089013593506080890135925060a089013591506122af60c08a01611eac565b90509295985092959890939650565b600080600080608085870312156122d457600080fd5b843567ffffffffffffffff8111156122eb57600080fd5b6122f787828801611fe8565b94505061230660208601612014565b93969395505050506040820135916060013590565b60006020828403121561232d57600080fd5b5051919050565b60006020828403121561234657600080fd5b61204082612000565b81835260208301925060008160005b8481101561238357612370868361238d565b604095860195919091019060010161235e565b5093949350505050565b6001600160a01b0361239e82611eac565b168252602090810135910152565b815160009082906020808601845b838110156123d6578151855293820193908201906001016123ba565b50929695505050505050565b8486823760008582016000815285516123ff818360208a016128d3565b018385823760009301928352509095945050505050565b600082516124288184602087016128d3565b9190910192915050565b6001600160a01b038416815260406020820152600061245560408301848661234f565b95945050505050565b82815260608101612040602083018480516001600160a01b03168252602090810151910152565b60208152600082518060208401526124a48160408501602087016128d3565b601f01601f19169190910160400192915050565b6060815260006124c88586612703565b60a060608501526124de6101008501828461234f565b9150506124ee6020870187612703565b8483037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa00160808601528083529091600091906020015b8183101561254a57612537818561238d565b6040938401936001939093019201612525565b61255660408a01611eac565b6001600160a01b03811660a0880152935061257360608a01612000565b63ffffffff811660c0880152935061258d60808a01612000565b63ffffffff1660e08701526001600160a01b038816602087015293506125b292505050565b826040830152949350505050565b6000808335601e198436030181126125d757600080fd5b83018035915067ffffffffffffffff8211156125f257600080fd5b6020019150600681901b3603821315611f8a57600080fd5b6000808335601e1984360301811261262157600080fd5b83018035915067ffffffffffffffff82111561263c57600080fd5b602001915036819003821315611f8a57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261242857600080fd5b60405160a0810167ffffffffffffffff811182821017156126a8576126a861295c565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156126d7576126d761295c565b604052919050565b600067ffffffffffffffff8211156126f9576126f961295c565b5060051b60200190565b6000808335601e1984360301811261271a57600080fd5b830160208101925035905067ffffffffffffffff81111561273a57600080fd5b8060061b3603831315611f8a57600080fd5b6000808585111561275c57600080fd5b8386111561276957600080fd5b5050820193919092039150565b600082198211156127895761278961291a565b500190565b6000826127ab57634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156127ca576127ca61291a565b500290565b600060a082360312156127e157600080fd5b6127e9612685565b823567ffffffffffffffff8082111561280157600080fd5b9084019036601f83011261281457600080fd5b81356020612824611ee9836126df565b8281528181019085830136600686901b88018501111561284357600080fd5b600096505b8487101561286f5761285a3682611f91565b83526001969096019591830191604001612848565b508652508681013593508284111561288657600080fd5b61289236858901611ec8565b81860152505050506128a660408401611eac565b60408201526128b760608401612000565b60608201526128c860808401612000565b608082015292915050565b60005b838110156128ee5781810151838201526020016128d6565b8381111561187e5750506000910152565b60006000198214156129135761291361291a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea264697066735822122050ff5cabe47edd9569ce89e0ba0f68eff813e85d665e712a723440f1d6f5cc4564736f6c63430008070033

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

00000000000000000000000042000000000000000000000000000000000000060000000000000000000000005ef7f250f74d4f11a68054ae4e150705474a6d4a

-----Decoded View---------------
Arg [0] : _wrappedNativeToken (address): 0x4200000000000000000000000000000000000006
Arg [1] : _bank (address): 0x5EF7F250f74d4F11A68054AE4e150705474a6D4a

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004200000000000000000000000000000000000006
Arg [1] : 0000000000000000000000005ef7f250f74d4f11a68054ae4e150705474a6d4a


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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