ETH Price: $2,506.68 (+0.29%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Swap191804542024-02-08 2:24:23486 days ago1707359063IN
0xca63f155...BFB283FD0
8 ETH0.0044350232.03898988
Swap191803482024-02-08 2:02:47486 days ago1707357767IN
0xca63f155...BFB283FD0
3.90969261 ETH0.0044931629.53970353
Swap190575222024-01-21 20:18:35503 days ago1705868315IN
0xca63f155...BFB283FD0
0 ETH0.0026521816.35384962
Swap190575142024-01-21 20:16:59503 days ago1705868219IN
0xca63f155...BFB283FD0
0 ETH0.003683716.39212076
Swap190430222024-01-19 19:32:47505 days ago1705692767IN
0xca63f155...BFB283FD0
0 ETH0.0070757936.20297195
Swap190192982024-01-16 11:58:11509 days ago1705406291IN
0xca63f155...BFB283FD0
0 ETH0.004676428.99648018
Swap188688302023-12-26 8:59:11530 days ago1703581151IN
0xca63f155...BFB283FD0
0 ETH0.0020041712.67598898
Swap188609552023-12-25 6:24:23531 days ago1703485463IN
0xca63f155...BFB283FD0
0.09246373 ETH0.0027115414.45842711
Swap188572312023-12-24 17:52:47531 days ago1703440367IN
0xca63f155...BFB283FD0
0.028 ETH0.0039103419.10887284
Swap188498822023-12-23 17:04:35532 days ago1703351075IN
0xca63f155...BFB283FD0
0.11 ETH0.0042139422.46920665
Swap188477262023-12-23 9:49:59533 days ago1703324999IN
0xca63f155...BFB283FD0
0 ETH0.0040518318.23910244
Swap186456342023-11-25 2:08:47561 days ago1700878127IN
0xca63f155...BFB283FD0
0 ETH0.0038096222.46018951
Swap186455722023-11-25 1:56:11561 days ago1700877371IN
0xca63f155...BFB283FD0
0 ETH0.0036471522.61042776
Swap185391532023-11-10 4:27:23576 days ago1699590443IN
0xca63f155...BFB283FD0
0 ETH0.0063855931.85866064
Swap185354662023-11-09 16:04:47576 days ago1699545887IN
0xca63f155...BFB283FD0
3 ETH0.02142061147.0600052
Swap185013582023-11-04 21:30:23581 days ago1699133423IN
0xca63f155...BFB283FD0
0 ETH0.0024954612.77079728
Swap184326522023-10-26 6:37:35591 days ago1698302255IN
0xca63f155...BFB283FD0
0.05 ETH0.0027718315.58576814
Swap183544162023-10-15 7:53:59602 days ago1697356439IN
0xca63f155...BFB283FD0
0.1 ETH0.00102255.7493795
Swap183402282023-10-13 8:17:59604 days ago1697185079IN
0xca63f155...BFB283FD0
0.1 ETH0.012046246.27084491
Swap183385072023-10-13 2:29:23604 days ago1697164163IN
0xca63f155...BFB283FD0
0 ETH0.000977755.76484165
Swap183334062023-10-12 9:20:59605 days ago1697102459IN
0xca63f155...BFB283FD0
0 ETH0.001308646.69563529
Swap182089322023-09-24 23:28:11622 days ago1695598091IN
0xca63f155...BFB283FD0
0.5 ETH0.001511058.17301929

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
Deposit191804542024-02-08 2:24:23486 days ago1707359063
0xca63f155...BFB283FD0
8 ETH
Deposit191803482024-02-08 2:02:47486 days ago1707357767
0xca63f155...BFB283FD0
3.90969261 ETH
Transfer190575222024-01-21 20:18:35503 days ago1705868315
0xca63f155...BFB283FD0
2.42205935 ETH
Transfer190575222024-01-21 20:18:35503 days ago1705868315
0xca63f155...BFB283FD0
2.42205935 ETH
Transfer190430222024-01-19 19:32:47505 days ago1705692767
0xca63f155...BFB283FD0
0.20072459 ETH
Transfer190430222024-01-19 19:32:47505 days ago1705692767
0xca63f155...BFB283FD0
0.20072459 ETH
Transfer190192982024-01-16 11:58:11509 days ago1705406291
0xca63f155...BFB283FD0
0.19765405 ETH
Transfer190192982024-01-16 11:58:11509 days ago1705406291
0xca63f155...BFB283FD0
0.19765405 ETH
Deposit189618072024-01-08 10:47:59517 days ago1704710879
0xca63f155...BFB283FD0
0.1485 ETH
Swap189618072024-01-08 10:47:59517 days ago1704710879
0xca63f155...BFB283FD0
0.1485 ETH
Deposit189470112024-01-06 8:32:11519 days ago1704529931
0xca63f155...BFB283FD0
0.792 ETH
Swap189470112024-01-06 8:32:11519 days ago1704529931
0xca63f155...BFB283FD0
0.792 ETH
Deposit188609552023-12-25 6:24:23531 days ago1703485463
0xca63f155...BFB283FD0
0.09246373 ETH
Deposit188572312023-12-24 17:52:47531 days ago1703440367
0xca63f155...BFB283FD0
0.028 ETH
Deposit188498822023-12-23 17:04:35532 days ago1703351075
0xca63f155...BFB283FD0
0.11 ETH
Transfer186456342023-11-25 2:08:47561 days ago1700878127
0xca63f155...BFB283FD0
0.31701634 ETH
Transfer186456342023-11-25 2:08:47561 days ago1700878127
0xca63f155...BFB283FD0
0.00001074 ETH
Transfer186456342023-11-25 2:08:47561 days ago1700878127
0xca63f155...BFB283FD0
0.31702709 ETH
Transfer186455722023-11-25 1:56:11561 days ago1700877371
0xca63f155...BFB283FD0
0.47932216 ETH
Transfer186455722023-11-25 1:56:11561 days ago1700877371
0xca63f155...BFB283FD0
0.47932216 ETH
Transfer185391532023-11-10 4:27:23576 days ago1699590443
0xca63f155...BFB283FD0
0.94227893 ETH
Transfer185391532023-11-10 4:27:23576 days ago1699590443
0xca63f155...BFB283FD0
0.94227893 ETH
Deposit185354662023-11-09 16:04:47576 days ago1699545887
0xca63f155...BFB283FD0
3 ETH
Transfer185013582023-11-04 21:30:23581 days ago1699133423
0xca63f155...BFB283FD0
0.05419127 ETH
Transfer185013582023-11-04 21:30:23581 days ago1699133423
0xca63f155...BFB283FD0
0.05419127 ETH
View All Internal Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Contract Source Code Verified (Exact Match)

Contract Name:
WowmaxRouter

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 800 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "./interfaces/IWETH.sol";
import "./interfaces/IWowmaxRouter.sol";

import "./libraries/UniswapV2.sol";
import "./libraries/UniswapV3.sol";
import "./libraries/Curve.sol";
import "./libraries/PancakeSwapStable.sol";
import "./libraries/DODOV2.sol";
import "./libraries/DODOV1.sol";
import "./libraries/Hashflow.sol";
import "./libraries/Saddle.sol";
import "./libraries/Wombat.sol";
import "./libraries/Level.sol";
import "./libraries/Fulcrom.sol";
import "./libraries/WooFi.sol";

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./WowmaxSwapReentrancyGuard.sol";

/// @title WOWMAX Router
/// @notice Router for stateless execution of swaps against multiple DEX protocols
contract WowmaxRouter is IWowmaxRouter, Ownable, WowmaxSwapReentrancyGuard {
    IWETH public WETH;
    address public treasury;

    bytes32 internal constant UNISWAP_V2 = "UNISWAP_V2";
    bytes32 internal constant UNISWAP_V3 = "UNISWAP_V3";
    bytes32 internal constant UNISWAP_V2_ROUTER = "UNISWAP_V2_ROUTER";
    bytes32 internal constant CURVE = "CURVE";
    bytes32 internal constant DODO_V1 = "DODO_V1";
    bytes32 internal constant DODO_V2 = "DODO_V2";
    bytes32 internal constant HASHFLOW = "HASHFLOW";
    bytes32 internal constant PANCAKESWAP_STABLE = "PANCAKESWAP_STABLE";
    bytes32 internal constant SADDLE = "SADDLE";
    bytes32 internal constant WOMBAT = "WOMBAT";
    bytes32 internal constant LEVEL = "LEVEL";
    bytes32 internal constant FULCROM = "FULCROM";
    bytes32 internal constant WOOFI = "WOOFI";

    using SafeERC20 for IERC20;

    constructor(address _weth, address _treasury) {
        require(_weth != address(0), "WOWMAX: Wrong WETH address");
        require(_treasury != address(0), "WOWMAX: Wrong treasury address");

        WETH = IWETH(_weth);
        treasury = _treasury;
    }

    receive() external payable {
        require(_msgSender() == payable(address(WETH)), "WOWMAX: Forbidden token transfer");
        // only accept native chain tokens via fallback from the wrapper contract
    }

    // @inheritdoc IWowmaxRouter
    function swap(
        ExchangeRequest calldata request
    ) external payable override reentrancyProtectedSwap returns (uint256[] memory amountsOut) {
        uint256 amountIn = receiveTokens(request);
        for (uint256 i = 0; i < request.exchangeRoutes.length; i++) {
            exchange(request.exchangeRoutes[i]);
        }
        amountsOut = sendTokens(request);

        emit SwapExecuted(
            msg.sender,
            request.from == address(0) ? address(WETH) : request.from,
            amountIn,
            request.to,
            amountsOut
        );
    }

    // @dev receives source tokens from account or wraps received value
    function receiveTokens(ExchangeRequest calldata request) private returns (uint256) {
        uint256 amountIn;
        if (msg.value > 0 && request.from == address(0) && request.amountIn == 0) {
            amountIn = msg.value;
            WETH.deposit{ value: amountIn }();
        } else {
            if (request.amountIn > 0) {
                amountIn = request.amountIn;
                IERC20(request.from).safeTransferFrom(msg.sender, address(this), amountIn);
            }
        }
        return amountIn;
    }

    // @dev transfers received tokens back to the caller
    function sendTokens(ExchangeRequest calldata request) private returns (uint256[] memory amountsOut) {
        amountsOut = new uint256[](request.to.length);
        uint256 amountOut;
        IERC20 token;
        for (uint256 i = 0; i < request.to.length; i++) {
            token = IERC20(request.to[i]);
            amountOut = token.balanceOf(address(this));

            uint256 amountExtra;
            if (amountOut > request.amountOutExpected[i]) {
                amountExtra = amountOut - request.amountOutExpected[i];
                amountsOut[i] = request.amountOutExpected[i];
            } else {
                require(
                    amountOut >= (request.amountOutExpected[i] * (10000 - request.slippage[i])) / 10000,
                    "WOWMAX: Insufficient output amount"
                );
                amountsOut[i] = amountOut;
            }

            if (address(token) == address(WETH)) {
                WETH.withdraw(amountOut);
            }

            transfer(token, treasury, amountExtra);
            transfer(token, msg.sender, amountsOut[i]);
        }
    }

    // @dev transfer token to a recipient, unwrapping native token if necessary
    function transfer(IERC20 token, address to, uint256 amount) private {
        //slither-disable-next-line incorrect-equality
        if (amount == 0) {
            return;
        }
        if (address(token) == address(WETH)) {
            //slither-disable-next-line arbitrary-send-eth //recipient is either a msg.sender or a treasury
            payable(to).transfer(amount);
        } else {
            token.safeTransfer(to, amount);
        }
    }

    // @dev executes a single exchange route
    function exchange(ExchangeRoute calldata exchangeRoute) private returns (uint256) {
        uint256 amountIn = IERC20(exchangeRoute.from).balanceOf(address(this));
        uint256 amountOut;
        for (uint256 i = 0; i < exchangeRoute.swaps.length; i++) {
            amountOut += executeSwap(
                exchangeRoute.from,
                (amountIn * exchangeRoute.swaps[i].part) / exchangeRoute.parts,
                exchangeRoute.swaps[i]
            );
        }
        return amountOut;
    }

    // @dev executes a single swap
    function executeSwap(address from, uint256 amountIn, Swap calldata swapData) private returns (uint256) {
        if (swapData.family == UNISWAP_V3) {
            return UniswapV3.swap(amountIn, swapData);
        } else if (swapData.family == HASHFLOW) {
            return Hashflow.swap(from, amountIn, swapData);
        } else if (swapData.family == WOMBAT) {
            return Wombat.swap(from, amountIn, swapData);
        } else if (swapData.family == LEVEL) {
            return Level.swap(from, amountIn, swapData);
        } else if (swapData.family == DODO_V2) {
            return DODOV2.swap(from, amountIn, swapData);
        } else if (swapData.family == WOOFI) {
            return WooFi.swap(from, amountIn, swapData);
        } else if (swapData.family == UNISWAP_V2) {
            return UniswapV2.swap(from, amountIn, swapData);
        } else if (swapData.family == CURVE) {
            return Curve.swap(from, amountIn, swapData);
        } else if (swapData.family == PANCAKESWAP_STABLE) {
            return PancakeSwapStable.swap(from, amountIn, swapData);
        } else if (swapData.family == DODO_V1) {
            return DODOV1.swap(from, amountIn, swapData);
        } else if (swapData.family == SADDLE) {
            return Saddle.swap(from, amountIn, swapData);
        } else if (swapData.family == FULCROM) {
            return Fulcrom.swap(from, amountIn, swapData);
        } else if (swapData.family == UNISWAP_V2_ROUTER) {
            return UniswapV2.routerSwap(from, amountIn, swapData);
        } else {
            revert("WOWMAX: Unknown DEX family");
        }
    }

    // Callbacks

    // @dev callback for UniswapV3, is not allowed to be executed outside of a swap operation
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata _data
    ) external onlyDuringSwap {
        UniswapV3.invokeCallback(amount0Delta, amount1Delta, _data);
    }

    // @dev callback for PancakeSwapV3, is not allowed to be executed outside of a swap operation
    function pancakeV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata _data
    ) external onlyDuringSwap {
        UniswapV3.invokeCallback(amount0Delta, amount1Delta, _data);
    }

    // Admin functions

    // @dev withdraws tokens from the contract, in case of leftovers after a swap, or invalid swap requests
    function withdraw(address token, uint256 amount) external onlyOwner {
        IERC20(token).safeTransfer(treasury, amount);
    }

    // @dev withdraws chain native tokens from the contract, in case of leftovers after a swap, or invalid swap requests
    function withdrawETH(uint256 amount) external onlyOwner {
        payable(treasury).transfer(amount);
    }
}

// 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);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (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() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

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

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

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

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

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

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// SPDX-License-Identifier: 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: BUSL-1.1
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

// @title Wrapped token ERC20 interface
interface IWETH is IERC20 {
    function deposit() external payable;

    function withdraw(uint wad) external;
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

// @title Router token swapping functionality
// @notice Functions for swapping tokens via WOWMAX
interface IWowmaxRouter {
    struct Swap {
        // target token address
        address to;
        // part of owned tokens to be swapped
        uint256 part;
        // contract address that performs the swap
        address addr;
        // contract DEX family
        bytes32 family;
        // additional data that is required for a specific DEX protocol
        bytes data;
    }

    struct ExchangeRoute {
        // source token address
        address from;
        // total parts of owned token
        uint256 parts;
        // array of swaps for a specified token
        Swap[] swaps;
    }

    struct ExchangeRequest {
        // source token address
        address from;
        // source token amount to swap
        uint256 amountIn;
        // target token addresses
        address[] to;
        // exchange routes
        ExchangeRoute[] exchangeRoutes;
        // slippage tolerance for each target token
        uint256[] slippage;
        // expected amount for each target token
        uint256[] amountOutExpected;
    }

    event SwapExecuted(
        address indexed account,
        address indexed from,
        uint256 amountIn,
        address[] to,
        uint256[] amountOut
    );

    // @notice Executes a token swap
    // @param request - swap request
    // @return amountsOut - array of amounts that were received for each target token
    // @dev if from token is address(0) and amountIn is 0,
    // then chain native token is used as a source token, and value is used as amountIn
    function swap(ExchangeRequest calldata request) external payable returns (uint256[] memory amountsOut);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title Curve pool interface
interface ICurvePool {
    function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external;
}

// @title Curve library
// @notice Functions to swap tokens on Curve like protocols
library Curve {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        (int128 i, int128 j) = abi.decode(swapData.data, (int128, int128));
        uint256 balanceBefore = IERC20(swapData.to).balanceOf(address(this));
        //slither-disable-next-line unused-return //it's safe to ignore
        IERC20(from).approve(swapData.addr, amountIn);
        ICurvePool(swapData.addr).exchange(i, j, amountIn, 0);
        amountOut = IERC20(swapData.to).balanceOf(address(this)) - balanceBefore;
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title DODO v1 pool interface
interface IDODOV1Pool {
    function sellBaseToken(uint256 amount, uint256 minReceiveQuote, bytes calldata data) external returns (uint256);

    function buyBaseToken(uint256 amount, uint256 maxPayQuote, bytes calldata data) external returns (uint256);
}

// @title DODO v1 library
// @notice Functions to swap tokens on DODO v1 protocol
library DODOV1 {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        //slither-disable-next-line unused-return //it's safe to ignore
        IERC20(from).approve(swapData.addr, amountIn);
        amountOut = IDODOV1Pool(swapData.addr).sellBaseToken(amountIn, 0, "");
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title DODO v2 pool interface
interface IDODOV2Pool {
    function sellBase(address to) external returns (uint256);

    function sellQuote(address to) external returns (uint256);
}

// @title DODO v2 library
// @notice Functions to swap tokens on DODO v2 protocol
library DODOV2 {
    uint8 internal constant BASE_TO_QUOTE = 0;

    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        IERC20(from).safeTransfer(swapData.addr, amountIn);
        uint8 direction = abi.decode(swapData.data, (uint8));

        if (direction == BASE_TO_QUOTE) {
            amountOut = IDODOV2Pool(swapData.addr).sellBase(address(this));
        } else {
            amountOut = IDODOV2Pool(swapData.addr).sellQuote(address(this));
        }
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title Fulcrom pool interface
interface IFulcromPool {
    function swap(address _tokenIn, address _tokenOut, address _receiver) external returns (uint256);
}

// @title Fulcrom library
// @notice Functions to swap tokens on Fulcrom protocol
library Fulcrom {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        IERC20(from).safeTransfer(swapData.addr, amountIn);
        amountOut = IFulcromPool(swapData.addr).swap(from, swapData.to, address(this));
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title Hashflow router interface
interface IHashflowRouter {
    struct RFQTQuote {
        address pool;
        address externalAccount;
        address trader;
        address effectiveTrader;
        address baseToken;
        address quoteToken;
        uint256 effectiveBaseTokenAmount;
        uint256 maxBaseTokenAmount;
        uint256 maxQuoteTokenAmount;
        uint256 quoteExpiry;
        uint256 nonce;
        bytes32 txid;
        bytes signature;
    }

    function tradeSingleHop(RFQTQuote calldata quote) external payable;
}

// @title Hashflow library
// @notice Functions to swap tokens on Hashflow protocol
library Hashflow {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        IHashflowRouter.RFQTQuote memory quote = abi.decode(swapData.data, (IHashflowRouter.RFQTQuote));
        //slither-disable-next-line unused-return //it's safe to ignore
        IERC20(from).approve(swapData.addr, amountIn);
        if (amountIn < quote.maxBaseTokenAmount) {
            quote.effectiveBaseTokenAmount = amountIn;
        }
        uint256 balanceBefore = IERC20(swapData.to).balanceOf(address(this));
        IHashflowRouter(swapData.addr).tradeSingleHop(quote);
        amountOut = IERC20(swapData.to).balanceOf(address(this)) - balanceBefore;
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title Level pool interface
interface ILevelPool {
    function swap(address _tokenIn, address _tokenOut, uint256 _minOut, address _to, bytes calldata extradata) external;
}

// @title Level library
// @notice Functions to swap tokens on Level protocol
library Level {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        IERC20(from).safeTransfer(swapData.addr, amountIn);
        uint256 balanceBefore = IERC20(swapData.to).balanceOf(address(this));
        ILevelPool(swapData.addr).swap(from, swapData.to, 0, address(this), new bytes(0));
        amountOut = IERC20(swapData.to).balanceOf(address(this)) - balanceBefore;
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title PancakeSwap pool interface
interface IPancakeStablePool {
    // @dev Same as Curve but uses uint256 instead of int128
    function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;
}

// @title PancakeSwap library
// @notice Functions to swap tokens on PancakeSwap like protocols
library PancakeSwapStable {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        (int128 i, int128 j) = abi.decode(swapData.data, (int128, int128));
        uint256 balanceBefore = IERC20(swapData.to).balanceOf(address(this));
        //slither-disable-next-line unused-return //it's safe to ignore
        IERC20(from).approve(swapData.addr, amountIn);
        IPancakeStablePool(swapData.addr).exchange(uint256(uint128(i)), uint256(uint128(j)), amountIn, 0);
        amountOut = IERC20(swapData.to).balanceOf(address(this)) - balanceBefore;
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title Saddle pool interface
interface ISaddlePool {
    function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external;
}

// @title Saddle library
// @notice Functions to swap tokens on Saddle protocol
library Saddle {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        (uint8 tokenIndexFrom, uint8 tokenIndexTo) = abi.decode(swapData.data, (uint8, uint8));
        uint256 balanceBefore = IERC20(swapData.to).balanceOf(address(this));
        //slither-disable-next-line unused-return //it's safe to ignore
        IERC20(from).approve(swapData.addr, amountIn);
        ISaddlePool(swapData.addr).swap(tokenIndexFrom, tokenIndexTo, amountIn, 0, type(uint256).max);
        amountOut = IERC20(swapData.to).balanceOf(address(this)) - balanceBefore;
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title Uniswap v2 pair interface
interface IUniswapV2Pair {
    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast);

    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;

    function router() external returns (address);
}

// @title Uniswap v2 router interface
interface IUniswapV2Router {
    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);
}

// @title Uniswap v2 library
// @notice Functions to swap tokens on Uniswap v2 and compatible protocols
library UniswapV2 {
    uint256 private constant feeDenominator = 10000;

    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        IERC20(from).safeTransfer(swapData.addr, amountIn);
        uint256 fee = abi.decode(swapData.data, (uint256));
        bool directSwap = IUniswapV2Pair(swapData.addr).token0() == from;
        (uint112 reserveIn, uint112 reserveOut) = getReserves(swapData.addr, directSwap);
        amountOut = getAmountOut(amountIn, reserveIn, reserveOut, fee);
        if (amountOut > 0) {
            IUniswapV2Pair(swapData.addr).swap(
                directSwap ? 0 : amountOut,
                directSwap ? amountOut : 0,
                address(this),
                new bytes(0)
            );
        }
    }

    function routerSwap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        IUniswapV2Router router = IUniswapV2Router(IUniswapV2Pair(swapData.addr).router());
        IERC20(from).safeApprove(address(router), amountIn);
        address[] memory path = new address[](2);
        path[0] = from;
        path[1] = swapData.to;
        return router.swapExactTokensForTokens(amountIn, 0, path, address(this), type(uint256).max)[1];
    }

    function getReserves(address pair, bool directSwap) private view returns (uint112 reserveIn, uint112 reserveOut) {
        (uint112 reserve0, uint112 reserve1, ) = IUniswapV2Pair(pair).getReserves();
        return directSwap ? (reserve0, reserve1) : (reserve1, reserve0);
    }

    function getAmountOut(
        uint256 amountIn,
        uint112 reserveIn,
        uint112 reserveOut,
        uint256 fee
    ) private pure returns (uint256 amountOut) {
        uint256 amountInWithFee = amountIn * (feeDenominator - fee);
        uint256 numerator = amountInWithFee * reserveOut;
        uint256 denominator = reserveIn * feeDenominator + amountInWithFee;
        amountOut = numerator / denominator;
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title Uniswap v3 pool interface
interface IUniswapV3Pool {
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 sqrtPriceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);

    function token0() external view returns (address);

    function token1() external view returns (address);
}

// @title Uniswap v3 library
// @notice Functions to swap tokens on Uniswap v3 and compatible protocol
library UniswapV3 {
    using SafeERC20 for IERC20;

    function swap(uint256 amountIn, IWowmaxRouter.Swap memory swapData) internal returns (uint256 amountOut) {
        bool zeroForOne = abi.decode(swapData.data, (bool));
        uint160 sqrtPriceLimitX96 = zeroForOne ? 4295128740 : 1461446703485210103287273052203988822378723970341;
        (int256 amount0, int256 amount1) = IUniswapV3Pool(swapData.addr).swap(
            address(this),
            zeroForOne,
            int256(amountIn),
            sqrtPriceLimitX96,
            new bytes(0)
        );
        amountOut = uint(zeroForOne ? -amount1 : -amount0);
    }

    function invokeCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata /*_data*/) internal {
        if (amount0Delta > 0 && amount1Delta < 0) {
            IERC20(IUniswapV3Pool(msg.sender).token0()).safeTransfer(msg.sender, uint256(amount0Delta));
        } else if (amount0Delta < 0 && amount1Delta > 0) {
            IERC20(IUniswapV3Pool(msg.sender).token1()).safeTransfer(msg.sender, uint256(amount1Delta));
        } else {
            revert("WOWMAX: Uniswap v3 invariant violation");
        }
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title Wombat pool interface
interface IWombatPool {
    function swap(
        address fromToken,
        address toToken,
        uint256 fromAmount,
        uint256 minimumToAmount,
        address to,
        uint256 deadline
    ) external returns (uint256 actualToAmount, uint256 haircut);
}

// @title Wombat library
// @notice Functions to swap tokens on Wombat protocol
library Wombat {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        IERC20(from).safeApprove(swapData.addr, amountIn);
        (amountOut, ) = IWombatPool(swapData.addr).swap(
            from,
            swapData.to,
            amountIn,
            0,
            address(this),
            type(uint256).max
        );
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWowmaxRouter.sol";

// @title WooFi pool interface
interface IWooFiPool {
    function swap(
        address fromToken,
        address toToken,
        uint256 fromAmount,
        uint256 minToAmount,
        address to,
        address rebateTo
    ) external returns (uint256 realToAmount);
}

// @title WooFi library
// @notice Functions to swap tokens on WooFi protocol
library WooFi {
    using SafeERC20 for IERC20;

    function swap(
        address from,
        uint256 amountIn,
        IWowmaxRouter.Swap memory swapData
    ) internal returns (uint256 amountOut) {
        IERC20(from).safeTransfer(swapData.addr, amountIn);
        amountOut = IWooFiPool(swapData.addr).swap(from, swapData.to, amountIn, 0, address(this), address(0x0));
    }
}

File 23 of 23 : WowmaxSwapReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// Based on OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.7;

/**
 * @dev Contract module that helps prevent reentrant swaps
 */
abstract contract WowmaxSwapReentrancyGuard {
    uint256 private constant _SWAP_IN_PROGRESS = 1;
    uint256 private constant _SWAP_NOT_IN_PROGRESS = 2;

    uint256 private _swapStatus;

    constructor() {
        _swapStatus = _SWAP_NOT_IN_PROGRESS;
    }

    /**
     * @dev Prevents a contract from calling swap, directly or indirectly
     */
    modifier reentrancyProtectedSwap() {
        _beforeSwap();
        _;
        _afterSwap();
    }

    /**
     * @dev Prevents operation from being called outside of swap
     */
    modifier onlyDuringSwap() {
        require(_swapStatus == _SWAP_IN_PROGRESS, "WOWMAX: not allowed outside of swap");
        _;
    }

    function _beforeSwap() private {
        require(_swapStatus != _SWAP_IN_PROGRESS, "WOWMAX: reentrant swap not allowed");
        _swapStatus = _SWAP_IN_PROGRESS;
    }

    function _afterSwap() private {
        _swapStatus = _SWAP_NOT_IN_PROGRESS;
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_weth","type":"address"},{"internalType":"address","name":"_treasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"to","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amountOut","type":"uint256[]"}],"name":"SwapExecuted","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"pancakeV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"to","type":"address[]"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"parts","type":"uint256"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"part","type":"uint256"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes32","name":"family","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IWowmaxRouter.Swap[]","name":"swaps","type":"tuple[]"}],"internalType":"struct IWowmaxRouter.ExchangeRoute[]","name":"exchangeRoutes","type":"tuple[]"},{"internalType":"uint256[]","name":"slippage","type":"uint256[]"},{"internalType":"uint256[]","name":"amountOutExpected","type":"uint256[]"}],"internalType":"struct IWowmaxRouter.ExchangeRequest","name":"request","type":"tuple"}],"name":"swap","outputs":[{"internalType":"uint256[]","name":"amountsOut","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b50604051620034f5380380620034f5833981016040819052620000349162000197565b6200003f336200012a565b60026001556001600160a01b038216620000a05760405162461bcd60e51b815260206004820152601a60248201527f574f574d41583a2057726f6e672057455448206164647265737300000000000060448201526064015b60405180910390fd5b6001600160a01b038116620000f85760405162461bcd60e51b815260206004820152601e60248201527f574f574d41583a2057726f6e6720747265617375727920616464726573730000604482015260640162000097565b600280546001600160a01b039384166001600160a01b03199182161790915560038054929093169116179055620001cf565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200019257600080fd5b919050565b60008060408385031215620001ab57600080fd5b620001b6836200017a565b9150620001c6602084016200017a565b90509250929050565b61331680620001df6000396000f3fe6080604052600436106100b45760003560e01c8063ad5c464811610069578063f2fde38b1161004e578063f2fde38b1461021c578063f3fef3a31461023c578063fa461e331461015157600080fd5b8063ad5c4648146101dc578063f14210a6146101fc57600080fd5b806361d027b31161009a57806361d027b314610171578063715018a6146101a95780638da5cb5b146101be57600080fd5b8062d5a9e81461012857806323a69e751461015157600080fd5b36610123576002546001600160a01b0316336001600160a01b0316146101215760405162461bcd60e51b815260206004820181905260248201527f574f574d41583a20466f7262696464656e20746f6b656e207472616e7366657260448201526064015b60405180910390fd5b005b600080fd5b61013b610136366004612b10565b61025c565b6040516101489190612e21565b60405180910390f35b34801561015d57600080fd5b5061012161016c366004612a90565b610380565b34801561017d57600080fd5b50600354610191906001600160a01b031681565b6040516001600160a01b039091168152602001610148565b3480156101b557600080fd5b506101216103ef565b3480156101ca57600080fd5b506000546001600160a01b0316610191565b3480156101e857600080fd5b50600254610191906001600160a01b031681565b34801561020857600080fd5b50610121610217366004612cb3565b610403565b34801561022857600080fd5b50610121610237366004612904565b610449565b34801561024857600080fd5b5061012161025736600461293e565b6104d9565b60606102666104fb565b60006102718361055e565b905060005b6102836060850185613044565b90508110156102d6576102c361029c6060860186613044565b838181106102ac576102ac6132c8565b90506020028101906102be919061308e565b61063d565b50806102ce8161327a565b915050610276565b506102e083610798565b915060006102f16020850185612904565b6001600160a01b0316146103115761030c6020840184612904565b61031e565b6002546001600160a01b03165b6001600160a01b0316337f25a3ab87780ac0e2eeeb645d408cbc89d66c72590ae0e1f81bda8f3d3a8d1216836103576040880188613044565b876040516103689493929190612f39565b60405180910390a35061037b6002600155565b919050565b60018054146103dd5760405162461bcd60e51b815260206004820152602360248201527f574f574d41583a206e6f7420616c6c6f776564206f757473696465206f66207360448201526207761760ec1b6064820152608401610118565b6103e984848484610b0e565b50505050565b6103f7610c6f565b6104016000610cc9565b565b61040b610c6f565b6003546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610445573d6000803e3d6000fd5b5050565b610451610c6f565b6001600160a01b0381166104cd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610118565b6104d681610cc9565b50565b6104e1610c6f565b600354610445906001600160a01b03848116911683610d31565b6001805414156105585760405162461bcd60e51b815260206004820152602260248201527f574f574d41583a207265656e7472616e742073776170206e6f7420616c6c6f77604482015261195960f21b6064820152608401610118565b60018055565b6000806000341180156105865750600061057b6020850185612904565b6001600160a01b0316145b801561059457506020830135155b15610600575060025460408051630d0e30db60e41b8152905134926001600160a01b03169163d0e30db091849160048082019260009290919082900301818588803b1580156105e257600080fd5b505af11580156105f6573d6000803e3d6000fd5b5050505050610637565b602083013515610637575060208201803590610637903390309084906106269088612904565b6001600160a01b0316929190610dc6565b92915050565b60008061064d6020840184612904565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561068e57600080fd5b505afa1580156106a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c69190612ccc565b90506000805b6106d96040860186613044565b9050811015610790576107726106f26020870187612904565b60208701356107046040890189613044565b85818110610714576107146132c8565b905060200281019061072691906130a4565b610734906020013587613177565b61073e9190613155565b61074b6040890189613044565b8581811061075b5761075b6132c8565b905060200281019061076d91906130a4565b610dfe565b61077c908361313d565b9150806107888161327a565b9150506106cc565b509392505050565b60606107a76040830183613044565b905067ffffffffffffffff8111156107c1576107c16132de565b6040519080825280602002602001820160405280156107ea578160200160208202803683370190505b50905060008060005b6108006040860186613044565b9050811015610b06576108166040860186613044565b82818110610826576108266132c8565b905060200201602081019061083b9190612904565b6040516370a0823160e01b81523060048201529092506001600160a01b038316906370a082319060240160206040518083038186803b15801561087d57600080fd5b505afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b59190612ccc565b925060006108c660a0870187613044565b838181106108d6576108d66132c8565b9050602002013584111561095c576108f160a0870187613044565b83818110610901576109016132c8565b90506020020135846109139190613196565b905061092260a0870187613044565b83818110610932576109326132c8565b9050602002013585838151811061094b5761094b6132c8565b602002602001018181525050610a42565b61271061096c6080880188613044565b8481811061097c5761097c6132c8565b905060200201356127106109909190613196565b61099d60a0890189613044565b858181106109ad576109ad6132c8565b905060200201356109be9190613177565b6109c89190613155565b841015610a225760405162461bcd60e51b815260206004820152602260248201527f574f574d41583a20496e73756666696369656e74206f757470757420616d6f756044820152611b9d60f21b6064820152608401610118565b83858381518110610a3557610a356132c8565b6020026020010181815250505b6002546001600160a01b0384811691161415610ab757600254604051632e1a7d4d60e01b8152600481018690526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b158015610a9e57600080fd5b505af1158015610ab2573d6000803e3d6000fd5b505050505b600354610acf9084906001600160a01b031683611188565b610af38333878581518110610ae657610ae66132c8565b6020026020010151611188565b5080610afe8161327a565b9150506107f3565b505050919050565b600084138015610b1e5750600083125b15610bae57610ba93385336001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6157600080fd5b505afa158015610b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b999190612921565b6001600160a01b03169190610d31565b6103e9565b600084128015610bbe5750600083135b15610c0157610ba93384336001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6157600080fd5b60405162461bcd60e51b815260206004820152602660248201527f574f574d41583a20556e697377617020763320696e76617269616e742076696f60448201527f6c6174696f6e00000000000000000000000000000000000000000000000000006064820152608401610118565b6000546001600160a01b031633146104015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610118565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b038316602482015260448101829052610dc190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526111f2565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526103e99085906323b872dd60e01b90608401610d5d565b60007f554e49535741505f56330000000000000000000000000000000000000000000082606001351415610e4557610e3e83610e39846131ad565b6112d7565b9050611181565b7f48415348464c4f5700000000000000000000000000000000000000000000000082606001351415610e8457610e3e8484610e7f856131ad565b6113e4565b7f574f4d424154000000000000000000000000000000000000000000000000000082606001351415610ec357610e3e8484610ebe856131ad565b61160d565b7f4c4556454c00000000000000000000000000000000000000000000000000000082606001351415610f0257610e3e8484610efd856131ad565b6116d8565b7f444f444f5f56320000000000000000000000000000000000000000000000000082606001351415610f4157610e3e8484610f3c856131ad565b61187c565b7f574f4f464900000000000000000000000000000000000000000000000000000082606001351415610f8057610e3e8484610f7b856131ad565b6119c2565b7f554e49535741505f56320000000000000000000000000000000000000000000082606001351415610fbf57610e3e8484610fba856131ad565b611a8d565b7f435552564500000000000000000000000000000000000000000000000000000082606001351415610ffe57610e3e8484610ff9856131ad565b611c34565b7f50414e43414b45535741505f535441424c4500000000000000000000000000008260600135141561103d57610e3e8484611038856131ad565b611e5f565b7f444f444f5f5631000000000000000000000000000000000000000000000000008260600135141561107c57610e3e8484611077856131ad565b611fe4565b7f534144444c450000000000000000000000000000000000000000000000000000826060013514156110bb57610e3e84846110b6856131ad565b6120b7565b7f46554c43524f4d00000000000000000000000000000000000000000000000000826060013514156110fa57610e3e84846110f5856131ad565b612235565b7f554e49535741505f56325f524f555445520000000000000000000000000000008260600135141561113957610e3e8484611134856131ad565b612295565b60405162461bcd60e51b815260206004820152601a60248201527f574f574d41583a20556e6b6e6f776e204445582066616d696c790000000000006044820152606401610118565b9392505050565b8061119257505050565b6002546001600160a01b03848116911614156111de576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156103e9573d6000803e3d6000fd5b610dc16001600160a01b0384168383610d31565b6000611247826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124539092919063ffffffff16565b805190915015610dc157808060200190518101906112659190612a17565b610dc15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610118565b60008082608001518060200190518101906112f29190612a17565b90506000816113155773fffd8963efd1fc6a506488495d951d5263988d2561131c565b6401000276a45b604085810151815160008082526020820193849052630251596160e31b909352929350909182916001600160a01b03169063128acb089061136890309088908c90899060248101612de7565b6040805180830381600087803b15801561138157600080fd5b505af1158015611395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b99190612a6c565b91509150836113d0576113cb82613295565b6113d9565b6113d981613295565b979650505050505050565b60008082608001518060200190518101906113ff9190612b4b565b604084810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810187905291925086169063095ea7b390604401602060405180830381600087803b15801561145157600080fd5b505af1158015611465573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114899190612a17565b508060e0015184101561149e5760c081018490525b82516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b1580156114e157600080fd5b505afa1580156114f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115199190612ccc565b905083604001516001600160a01b031663f0210929836040518263ffffffff1660e01b815260040161154b9190612e47565b600060405180830381600087803b15801561156557600080fd5b505af1158015611579573d6000803e3d6000fd5b505085516040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a082319060240160206040518083038186803b1580156115c157600080fd5b505afa1580156115d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f99190612ccc565b6116039190613196565b9695505050505050565b604081015160009061162a906001600160a01b0386169085612462565b60408281015183519151639908fc8b60e01b81526001600160a01b0387811660048301529283166024820152604481018690526000606482015230608482015260001960a4820152911690639908fc8b9060c4016040805180830381600087803b15801561169757600080fd5b505af11580156116ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cf9190612a6c565b50949350505050565b60408101516000906116f5906001600160a01b0386169085610d31565b81516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561173857600080fd5b505afa15801561174c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117709190612ccc565b6040848101518551825160008082526020820194859052631fa196a960e21b9094529394506001600160a01b0390911692637e865aa4926117bb928a92909190309060248101612dad565b600060405180830381600087803b1580156117d557600080fd5b505af11580156117e9573d6000803e3d6000fd5b505084516040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a082319060240160206040518083038186803b15801561183157600080fd5b505afa158015611845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118699190612ccc565b6118739190613196565b95945050505050565b6040810151600090611899906001600160a01b0386169085610d31565b600082608001518060200190518101906118b39190612ce5565b905060ff8116611943576040808401519051632f58056d60e21b81523060048201526001600160a01b039091169063bd6015b490602401602060405180830381600087803b15801561190457600080fd5b505af1158015611918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193c9190612ccc565b9150610790565b6040808401519051636ec9facd60e11b81523060048201526001600160a01b039091169063dd93f59a90602401602060405180830381600087803b15801561198a57600080fd5b505af115801561199e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118739190612ccc565b60408101516000906119df906001600160a01b0386169085610d31565b60408281015183519151633ee101c160e11b81526001600160a01b03878116600483015292831660248201526044810186905260006064820181905230608483015260a4820152911690637dc203829060c4015b602060405180830381600087803b158015611a4d57600080fd5b505af1158015611a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a859190612ccc565b949350505050565b6040810151600090611aaa906001600160a01b0386169085610d31565b60008260800151806020019051810190611ac49190612ccc565b90506000856001600160a01b031684604001516001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0f57600080fd5b505afa158015611b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b479190612921565b6001600160a01b0316149050600080611b6486604001518461258d565b91509150611b7487838387612626565b94508415611c295785604001516001600160a01b031663022c0d9f84611b9a5786611b9d565b60005b85611ba9576000611bab565b875b604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16909152611bf6929190309060248101613016565b600060405180830381600087803b158015611c1057600080fd5b505af1158015611c24573d6000803e3d6000fd5b505050505b505050509392505050565b60008060008360800151806020019051810190611c519190612a39565b85516040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015611c9c57600080fd5b505afa158015611cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd49190612ccc565b604086810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810189905291925088169063095ea7b390604401602060405180830381600087803b158015611d2657600080fd5b505af1158015611d3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5e9190612a17565b506040808601519051630f7c084960e21b8152600f85810b600483015284900b602482015260448101889052600060648201526001600160a01b0390911690633df02124906084015b600060405180830381600087803b158015611dc157600080fd5b505af1158015611dd5573d6000803e3d6000fd5b505086516040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a082319060240160206040518083038186803b158015611e1d57600080fd5b505afa158015611e31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e559190612ccc565b6113d99190613196565b60008060008360800151806020019051810190611e7c9190612a39565b85516040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190612ccc565b604086810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810189905291925088169063095ea7b390604401602060405180830381600087803b158015611f5157600080fd5b505af1158015611f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f899190612a17565b506040808601519051630b68372160e31b81526fffffffffffffffffffffffffffffffff80861660048301528416602482015260448101889052600060648201526001600160a01b0390911690635b41b90890608401611da7565b604081810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810184905260009185169063095ea7b390604401602060405180830381600087803b15801561203657600080fd5b505af115801561204a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206e9190612a17565b506040808301519051638dae733360e01b8152600481018590526000602482018190526060604483015260648201526001600160a01b0390911690638dae733390608401611a33565b600080600083608001518060200190518101906120d49190612d00565b85516040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a082319060240160206040518083038186803b15801561211f57600080fd5b505afa158015612133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121579190612ccc565b604086810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810189905291925088169063095ea7b390604401602060405180830381600087803b1580156121a957600080fd5b505af11580156121bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e19190612a17565b5060408086015190516348b4aac360e11b815260ff808616600483015284166024820152604481018890526000606482015260001960848201526001600160a01b039091169063916955869060a401611da7565b6040810151600090612252906001600160a01b0386169085610d31565b60408281015183519151634998b10960e11b81526001600160a01b0387811660048301529283166024820152306044820152911690639331621290606401611a33565b60008082604001516001600160a01b031663f887ea406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156122d757600080fd5b505af11580156122eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230f9190612921565b90506123256001600160a01b0386168286612462565b604080516002808252606082018352600092602083019080368337019050509050858160008151811061235a5761235a6132c8565b60200260200101906001600160a01b031690816001600160a01b031681525050836000015181600181518110612392576123926132c8565b6001600160a01b0392831660209182029290920101526040516338ed173960e01b8152908316906338ed1739906123d89088906000908690309060001990600401612fa5565b600060405180830381600087803b1580156123f257600080fd5b505af1158015612406573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261242e919081019061296a565b600181518110612440576124406132c8565b6020026020010151925050509392505050565b6060611a8584846000856126a0565b8015806124eb5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156124b157600080fd5b505afa1580156124c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e99190612ccc565b155b61255d5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610118565b6040516001600160a01b038316602482015260448101829052610dc190849063095ea7b360e01b90606401610d5d565b600080600080856001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b1580156125cc57600080fd5b505afa1580156125e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126049190612c63565b509150915084612615578082612618565b81815b9350935050505b9250929050565b60008061263583612710613196565b61263f9087613177565b9050600061265d6dffffffffffffffffffffffffffff861683613177565b905060008261267e6127106dffffffffffffffffffffffffffff8a16613177565b612688919061313d565b90506126948183613155565b98975050505050505050565b6060824710156127185760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610118565b600080866001600160a01b031685876040516127349190612d91565b60006040518083038185875af1925050503d8060008114612771576040519150601f19603f3d011682016040523d82523d6000602084013e612776565b606091505b50915091506113d987838387606083156127ee5782516127e7576001600160a01b0385163b6127e75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610118565b5081611a85565b611a8583838151156128035781518083602001fd5b8060405162461bcd60e51b81526004016101189190612e34565b805161037b816132f4565b600082601f83011261283957600080fd5b813561284c61284782613115565b6130e4565b81815284602083860101111561286157600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261288f57600080fd5b815161289d61284782613115565b8181528460208386010111156128b257600080fd5b611a8582602083016020870161324e565b8051600f81900b811461037b57600080fd5b80516dffffffffffffffffffffffffffff8116811461037b57600080fd5b805160ff8116811461037b57600080fd5b60006020828403121561291657600080fd5b8135611181816132f4565b60006020828403121561293357600080fd5b8151611181816132f4565b6000806040838503121561295157600080fd5b823561295c816132f4565b946020939093013593505050565b6000602080838503121561297d57600080fd5b825167ffffffffffffffff8082111561299557600080fd5b818501915085601f8301126129a957600080fd5b8151818111156129bb576129bb6132de565b8060051b91506129cc8483016130e4565b8181528481019084860184860187018a10156129e757600080fd5b600095505b83861015612a0a5780518352600195909501949186019186016129ec565b5098975050505050505050565b600060208284031215612a2957600080fd5b8151801515811461118157600080fd5b60008060408385031215612a4c57600080fd5b612a55836128c3565b9150612a63602084016128c3565b90509250929050565b60008060408385031215612a7f57600080fd5b505080516020909101519092909150565b60008060008060608587031215612aa657600080fd5b8435935060208501359250604085013567ffffffffffffffff80821115612acc57600080fd5b818701915087601f830112612ae057600080fd5b813581811115612aef57600080fd5b886020828501011115612b0157600080fd5b95989497505060200194505050565b600060208284031215612b2257600080fd5b813567ffffffffffffffff811115612b3957600080fd5b820160c0818503121561118157600080fd5b600060208284031215612b5d57600080fd5b815167ffffffffffffffff80821115612b7557600080fd5b908301906101a08286031215612b8a57600080fd5b612b926130ba565b612b9b8361281d565b8152612ba96020840161281d565b6020820152612bba6040840161281d565b6040820152612bcb6060840161281d565b6060820152612bdc6080840161281d565b6080820152612bed60a0840161281d565b60a082015260c0838101519082015260e0808401519082015261010080840151908201526101208084015190820152610140808401519082015261016080840151908201526101808084015183811115612c4657600080fd5b612c528882870161287e565b918301919091525095945050505050565b600080600060608486031215612c7857600080fd5b612c81846128d5565b9250612c8f602085016128d5565b9150604084015163ffffffff81168114612ca857600080fd5b809150509250925092565b600060208284031215612cc557600080fd5b5035919050565b600060208284031215612cde57600080fd5b5051919050565b600060208284031215612cf757600080fd5b611181826128f3565b60008060408385031215612d1357600080fd5b612d1c836128f3565b9150612a63602084016128f3565b600081518084526020808501945080840160005b83811015612d5a57815187529582019590820190600101612d3e565b509495945050505050565b60008151808452612d7d81602086016020860161324e565b601f01601f19169290920160200192915050565b60008251612da381846020870161324e565b9190910192915050565b60006001600160a01b038088168352808716602084015285604084015280851660608401525060a060808301526113d960a0830184612d65565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a060808301526113d960a0830184612d65565b6020815260006111816020830184612d2a565b6020815260006111816020830184612d65565b60208152612e616020820183516001600160a01b03169052565b60006020830151612e7d60408401826001600160a01b03169052565b5060408301516001600160a01b03811660608401525060608301516001600160a01b03811660808401525060808301516001600160a01b03811660a08401525060a08301516001600160a01b03811660c08401525060c083015160e08381019190915283015161010080840191909152830151610120808401919091528301516101408084019190915283015161016080840191909152830151610180808401919091528301516101a080840152611a856101c0840182612d65565b84815260606020808301829052908201849052600090859060808401835b87811015612f85578335612f6a816132f4565b6001600160a01b031682529282019290820190600101612f57565b508481036040860152612f988187612d2a565b9998505050505050505050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b81811015612ff55784516001600160a01b031683529383019391830191600101612fd0565b50506001600160a01b03969096166060850152505050608001529392505050565b8481528360208201526001600160a01b03831660408201526080606082015260006116036080830184612d65565b6000808335601e1984360301811261305b57600080fd5b83018035915067ffffffffffffffff82111561307657600080fd5b6020019150600581901b360382131561261f57600080fd5b60008235605e19833603018112612da357600080fd5b60008235609e19833603018112612da357600080fd5b6040516101a0810167ffffffffffffffff811182821017156130de576130de6132de565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561310d5761310d6132de565b604052919050565b600067ffffffffffffffff82111561312f5761312f6132de565b50601f01601f191660200190565b60008219821115613150576131506132b2565b500190565b60008261317257634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613191576131916132b2565b500290565b6000828210156131a8576131a86132b2565b500390565b600060a082360312156131bf57600080fd5b60405160a0810167ffffffffffffffff82821081831117156131e3576131e36132de565b81604052843591506131f4826132f4565b8183526020850135602084015260408501359150613211826132f4565b81604084015260608501356060840152608085013591508082111561323557600080fd5b5061324236828601612828565b60808301525092915050565b60005b83811015613269578181015183820152602001613251565b838111156103e95750506000910152565b600060001982141561328e5761328e6132b2565b5060010190565b6000600160ff1b8214156132ab576132ab6132b2565b5060000390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146104d657600080fdfea164736f6c6343000807000a000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000bd4a0f12293c54e4e8ad221271cf0d395dd60a71

Deployed Bytecode

0x6080604052600436106100b45760003560e01c8063ad5c464811610069578063f2fde38b1161004e578063f2fde38b1461021c578063f3fef3a31461023c578063fa461e331461015157600080fd5b8063ad5c4648146101dc578063f14210a6146101fc57600080fd5b806361d027b31161009a57806361d027b314610171578063715018a6146101a95780638da5cb5b146101be57600080fd5b8062d5a9e81461012857806323a69e751461015157600080fd5b36610123576002546001600160a01b0316336001600160a01b0316146101215760405162461bcd60e51b815260206004820181905260248201527f574f574d41583a20466f7262696464656e20746f6b656e207472616e7366657260448201526064015b60405180910390fd5b005b600080fd5b61013b610136366004612b10565b61025c565b6040516101489190612e21565b60405180910390f35b34801561015d57600080fd5b5061012161016c366004612a90565b610380565b34801561017d57600080fd5b50600354610191906001600160a01b031681565b6040516001600160a01b039091168152602001610148565b3480156101b557600080fd5b506101216103ef565b3480156101ca57600080fd5b506000546001600160a01b0316610191565b3480156101e857600080fd5b50600254610191906001600160a01b031681565b34801561020857600080fd5b50610121610217366004612cb3565b610403565b34801561022857600080fd5b50610121610237366004612904565b610449565b34801561024857600080fd5b5061012161025736600461293e565b6104d9565b60606102666104fb565b60006102718361055e565b905060005b6102836060850185613044565b90508110156102d6576102c361029c6060860186613044565b838181106102ac576102ac6132c8565b90506020028101906102be919061308e565b61063d565b50806102ce8161327a565b915050610276565b506102e083610798565b915060006102f16020850185612904565b6001600160a01b0316146103115761030c6020840184612904565b61031e565b6002546001600160a01b03165b6001600160a01b0316337f25a3ab87780ac0e2eeeb645d408cbc89d66c72590ae0e1f81bda8f3d3a8d1216836103576040880188613044565b876040516103689493929190612f39565b60405180910390a35061037b6002600155565b919050565b60018054146103dd5760405162461bcd60e51b815260206004820152602360248201527f574f574d41583a206e6f7420616c6c6f776564206f757473696465206f66207360448201526207761760ec1b6064820152608401610118565b6103e984848484610b0e565b50505050565b6103f7610c6f565b6104016000610cc9565b565b61040b610c6f565b6003546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610445573d6000803e3d6000fd5b5050565b610451610c6f565b6001600160a01b0381166104cd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610118565b6104d681610cc9565b50565b6104e1610c6f565b600354610445906001600160a01b03848116911683610d31565b6001805414156105585760405162461bcd60e51b815260206004820152602260248201527f574f574d41583a207265656e7472616e742073776170206e6f7420616c6c6f77604482015261195960f21b6064820152608401610118565b60018055565b6000806000341180156105865750600061057b6020850185612904565b6001600160a01b0316145b801561059457506020830135155b15610600575060025460408051630d0e30db60e41b8152905134926001600160a01b03169163d0e30db091849160048082019260009290919082900301818588803b1580156105e257600080fd5b505af11580156105f6573d6000803e3d6000fd5b5050505050610637565b602083013515610637575060208201803590610637903390309084906106269088612904565b6001600160a01b0316929190610dc6565b92915050565b60008061064d6020840184612904565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561068e57600080fd5b505afa1580156106a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c69190612ccc565b90506000805b6106d96040860186613044565b9050811015610790576107726106f26020870187612904565b60208701356107046040890189613044565b85818110610714576107146132c8565b905060200281019061072691906130a4565b610734906020013587613177565b61073e9190613155565b61074b6040890189613044565b8581811061075b5761075b6132c8565b905060200281019061076d91906130a4565b610dfe565b61077c908361313d565b9150806107888161327a565b9150506106cc565b509392505050565b60606107a76040830183613044565b905067ffffffffffffffff8111156107c1576107c16132de565b6040519080825280602002602001820160405280156107ea578160200160208202803683370190505b50905060008060005b6108006040860186613044565b9050811015610b06576108166040860186613044565b82818110610826576108266132c8565b905060200201602081019061083b9190612904565b6040516370a0823160e01b81523060048201529092506001600160a01b038316906370a082319060240160206040518083038186803b15801561087d57600080fd5b505afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b59190612ccc565b925060006108c660a0870187613044565b838181106108d6576108d66132c8565b9050602002013584111561095c576108f160a0870187613044565b83818110610901576109016132c8565b90506020020135846109139190613196565b905061092260a0870187613044565b83818110610932576109326132c8565b9050602002013585838151811061094b5761094b6132c8565b602002602001018181525050610a42565b61271061096c6080880188613044565b8481811061097c5761097c6132c8565b905060200201356127106109909190613196565b61099d60a0890189613044565b858181106109ad576109ad6132c8565b905060200201356109be9190613177565b6109c89190613155565b841015610a225760405162461bcd60e51b815260206004820152602260248201527f574f574d41583a20496e73756666696369656e74206f757470757420616d6f756044820152611b9d60f21b6064820152608401610118565b83858381518110610a3557610a356132c8565b6020026020010181815250505b6002546001600160a01b0384811691161415610ab757600254604051632e1a7d4d60e01b8152600481018690526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b158015610a9e57600080fd5b505af1158015610ab2573d6000803e3d6000fd5b505050505b600354610acf9084906001600160a01b031683611188565b610af38333878581518110610ae657610ae66132c8565b6020026020010151611188565b5080610afe8161327a565b9150506107f3565b505050919050565b600084138015610b1e5750600083125b15610bae57610ba93385336001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6157600080fd5b505afa158015610b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b999190612921565b6001600160a01b03169190610d31565b6103e9565b600084128015610bbe5750600083135b15610c0157610ba93384336001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6157600080fd5b60405162461bcd60e51b815260206004820152602660248201527f574f574d41583a20556e697377617020763320696e76617269616e742076696f60448201527f6c6174696f6e00000000000000000000000000000000000000000000000000006064820152608401610118565b6000546001600160a01b031633146104015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610118565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b038316602482015260448101829052610dc190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526111f2565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526103e99085906323b872dd60e01b90608401610d5d565b60007f554e49535741505f56330000000000000000000000000000000000000000000082606001351415610e4557610e3e83610e39846131ad565b6112d7565b9050611181565b7f48415348464c4f5700000000000000000000000000000000000000000000000082606001351415610e8457610e3e8484610e7f856131ad565b6113e4565b7f574f4d424154000000000000000000000000000000000000000000000000000082606001351415610ec357610e3e8484610ebe856131ad565b61160d565b7f4c4556454c00000000000000000000000000000000000000000000000000000082606001351415610f0257610e3e8484610efd856131ad565b6116d8565b7f444f444f5f56320000000000000000000000000000000000000000000000000082606001351415610f4157610e3e8484610f3c856131ad565b61187c565b7f574f4f464900000000000000000000000000000000000000000000000000000082606001351415610f8057610e3e8484610f7b856131ad565b6119c2565b7f554e49535741505f56320000000000000000000000000000000000000000000082606001351415610fbf57610e3e8484610fba856131ad565b611a8d565b7f435552564500000000000000000000000000000000000000000000000000000082606001351415610ffe57610e3e8484610ff9856131ad565b611c34565b7f50414e43414b45535741505f535441424c4500000000000000000000000000008260600135141561103d57610e3e8484611038856131ad565b611e5f565b7f444f444f5f5631000000000000000000000000000000000000000000000000008260600135141561107c57610e3e8484611077856131ad565b611fe4565b7f534144444c450000000000000000000000000000000000000000000000000000826060013514156110bb57610e3e84846110b6856131ad565b6120b7565b7f46554c43524f4d00000000000000000000000000000000000000000000000000826060013514156110fa57610e3e84846110f5856131ad565b612235565b7f554e49535741505f56325f524f555445520000000000000000000000000000008260600135141561113957610e3e8484611134856131ad565b612295565b60405162461bcd60e51b815260206004820152601a60248201527f574f574d41583a20556e6b6e6f776e204445582066616d696c790000000000006044820152606401610118565b9392505050565b8061119257505050565b6002546001600160a01b03848116911614156111de576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156103e9573d6000803e3d6000fd5b610dc16001600160a01b0384168383610d31565b6000611247826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124539092919063ffffffff16565b805190915015610dc157808060200190518101906112659190612a17565b610dc15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610118565b60008082608001518060200190518101906112f29190612a17565b90506000816113155773fffd8963efd1fc6a506488495d951d5263988d2561131c565b6401000276a45b604085810151815160008082526020820193849052630251596160e31b909352929350909182916001600160a01b03169063128acb089061136890309088908c90899060248101612de7565b6040805180830381600087803b15801561138157600080fd5b505af1158015611395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b99190612a6c565b91509150836113d0576113cb82613295565b6113d9565b6113d981613295565b979650505050505050565b60008082608001518060200190518101906113ff9190612b4b565b604084810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810187905291925086169063095ea7b390604401602060405180830381600087803b15801561145157600080fd5b505af1158015611465573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114899190612a17565b508060e0015184101561149e5760c081018490525b82516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b1580156114e157600080fd5b505afa1580156114f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115199190612ccc565b905083604001516001600160a01b031663f0210929836040518263ffffffff1660e01b815260040161154b9190612e47565b600060405180830381600087803b15801561156557600080fd5b505af1158015611579573d6000803e3d6000fd5b505085516040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a082319060240160206040518083038186803b1580156115c157600080fd5b505afa1580156115d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f99190612ccc565b6116039190613196565b9695505050505050565b604081015160009061162a906001600160a01b0386169085612462565b60408281015183519151639908fc8b60e01b81526001600160a01b0387811660048301529283166024820152604481018690526000606482015230608482015260001960a4820152911690639908fc8b9060c4016040805180830381600087803b15801561169757600080fd5b505af11580156116ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cf9190612a6c565b50949350505050565b60408101516000906116f5906001600160a01b0386169085610d31565b81516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561173857600080fd5b505afa15801561174c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117709190612ccc565b6040848101518551825160008082526020820194859052631fa196a960e21b9094529394506001600160a01b0390911692637e865aa4926117bb928a92909190309060248101612dad565b600060405180830381600087803b1580156117d557600080fd5b505af11580156117e9573d6000803e3d6000fd5b505084516040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a082319060240160206040518083038186803b15801561183157600080fd5b505afa158015611845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118699190612ccc565b6118739190613196565b95945050505050565b6040810151600090611899906001600160a01b0386169085610d31565b600082608001518060200190518101906118b39190612ce5565b905060ff8116611943576040808401519051632f58056d60e21b81523060048201526001600160a01b039091169063bd6015b490602401602060405180830381600087803b15801561190457600080fd5b505af1158015611918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193c9190612ccc565b9150610790565b6040808401519051636ec9facd60e11b81523060048201526001600160a01b039091169063dd93f59a90602401602060405180830381600087803b15801561198a57600080fd5b505af115801561199e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118739190612ccc565b60408101516000906119df906001600160a01b0386169085610d31565b60408281015183519151633ee101c160e11b81526001600160a01b03878116600483015292831660248201526044810186905260006064820181905230608483015260a4820152911690637dc203829060c4015b602060405180830381600087803b158015611a4d57600080fd5b505af1158015611a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a859190612ccc565b949350505050565b6040810151600090611aaa906001600160a01b0386169085610d31565b60008260800151806020019051810190611ac49190612ccc565b90506000856001600160a01b031684604001516001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0f57600080fd5b505afa158015611b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b479190612921565b6001600160a01b0316149050600080611b6486604001518461258d565b91509150611b7487838387612626565b94508415611c295785604001516001600160a01b031663022c0d9f84611b9a5786611b9d565b60005b85611ba9576000611bab565b875b604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16909152611bf6929190309060248101613016565b600060405180830381600087803b158015611c1057600080fd5b505af1158015611c24573d6000803e3d6000fd5b505050505b505050509392505050565b60008060008360800151806020019051810190611c519190612a39565b85516040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015611c9c57600080fd5b505afa158015611cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd49190612ccc565b604086810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810189905291925088169063095ea7b390604401602060405180830381600087803b158015611d2657600080fd5b505af1158015611d3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5e9190612a17565b506040808601519051630f7c084960e21b8152600f85810b600483015284900b602482015260448101889052600060648201526001600160a01b0390911690633df02124906084015b600060405180830381600087803b158015611dc157600080fd5b505af1158015611dd5573d6000803e3d6000fd5b505086516040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a082319060240160206040518083038186803b158015611e1d57600080fd5b505afa158015611e31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e559190612ccc565b6113d99190613196565b60008060008360800151806020019051810190611e7c9190612a39565b85516040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190612ccc565b604086810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810189905291925088169063095ea7b390604401602060405180830381600087803b158015611f5157600080fd5b505af1158015611f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f899190612a17565b506040808601519051630b68372160e31b81526fffffffffffffffffffffffffffffffff80861660048301528416602482015260448101889052600060648201526001600160a01b0390911690635b41b90890608401611da7565b604081810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810184905260009185169063095ea7b390604401602060405180830381600087803b15801561203657600080fd5b505af115801561204a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206e9190612a17565b506040808301519051638dae733360e01b8152600481018590526000602482018190526060604483015260648201526001600160a01b0390911690638dae733390608401611a33565b600080600083608001518060200190518101906120d49190612d00565b85516040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a082319060240160206040518083038186803b15801561211f57600080fd5b505afa158015612133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121579190612ccc565b604086810151905163095ea7b360e01b81526001600160a01b0391821660048201526024810189905291925088169063095ea7b390604401602060405180830381600087803b1580156121a957600080fd5b505af11580156121bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e19190612a17565b5060408086015190516348b4aac360e11b815260ff808616600483015284166024820152604481018890526000606482015260001960848201526001600160a01b039091169063916955869060a401611da7565b6040810151600090612252906001600160a01b0386169085610d31565b60408281015183519151634998b10960e11b81526001600160a01b0387811660048301529283166024820152306044820152911690639331621290606401611a33565b60008082604001516001600160a01b031663f887ea406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156122d757600080fd5b505af11580156122eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230f9190612921565b90506123256001600160a01b0386168286612462565b604080516002808252606082018352600092602083019080368337019050509050858160008151811061235a5761235a6132c8565b60200260200101906001600160a01b031690816001600160a01b031681525050836000015181600181518110612392576123926132c8565b6001600160a01b0392831660209182029290920101526040516338ed173960e01b8152908316906338ed1739906123d89088906000908690309060001990600401612fa5565b600060405180830381600087803b1580156123f257600080fd5b505af1158015612406573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261242e919081019061296a565b600181518110612440576124406132c8565b6020026020010151925050509392505050565b6060611a8584846000856126a0565b8015806124eb5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156124b157600080fd5b505afa1580156124c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e99190612ccc565b155b61255d5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610118565b6040516001600160a01b038316602482015260448101829052610dc190849063095ea7b360e01b90606401610d5d565b600080600080856001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b1580156125cc57600080fd5b505afa1580156125e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126049190612c63565b509150915084612615578082612618565b81815b9350935050505b9250929050565b60008061263583612710613196565b61263f9087613177565b9050600061265d6dffffffffffffffffffffffffffff861683613177565b905060008261267e6127106dffffffffffffffffffffffffffff8a16613177565b612688919061313d565b90506126948183613155565b98975050505050505050565b6060824710156127185760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610118565b600080866001600160a01b031685876040516127349190612d91565b60006040518083038185875af1925050503d8060008114612771576040519150601f19603f3d011682016040523d82523d6000602084013e612776565b606091505b50915091506113d987838387606083156127ee5782516127e7576001600160a01b0385163b6127e75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610118565b5081611a85565b611a8583838151156128035781518083602001fd5b8060405162461bcd60e51b81526004016101189190612e34565b805161037b816132f4565b600082601f83011261283957600080fd5b813561284c61284782613115565b6130e4565b81815284602083860101111561286157600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261288f57600080fd5b815161289d61284782613115565b8181528460208386010111156128b257600080fd5b611a8582602083016020870161324e565b8051600f81900b811461037b57600080fd5b80516dffffffffffffffffffffffffffff8116811461037b57600080fd5b805160ff8116811461037b57600080fd5b60006020828403121561291657600080fd5b8135611181816132f4565b60006020828403121561293357600080fd5b8151611181816132f4565b6000806040838503121561295157600080fd5b823561295c816132f4565b946020939093013593505050565b6000602080838503121561297d57600080fd5b825167ffffffffffffffff8082111561299557600080fd5b818501915085601f8301126129a957600080fd5b8151818111156129bb576129bb6132de565b8060051b91506129cc8483016130e4565b8181528481019084860184860187018a10156129e757600080fd5b600095505b83861015612a0a5780518352600195909501949186019186016129ec565b5098975050505050505050565b600060208284031215612a2957600080fd5b8151801515811461118157600080fd5b60008060408385031215612a4c57600080fd5b612a55836128c3565b9150612a63602084016128c3565b90509250929050565b60008060408385031215612a7f57600080fd5b505080516020909101519092909150565b60008060008060608587031215612aa657600080fd5b8435935060208501359250604085013567ffffffffffffffff80821115612acc57600080fd5b818701915087601f830112612ae057600080fd5b813581811115612aef57600080fd5b886020828501011115612b0157600080fd5b95989497505060200194505050565b600060208284031215612b2257600080fd5b813567ffffffffffffffff811115612b3957600080fd5b820160c0818503121561118157600080fd5b600060208284031215612b5d57600080fd5b815167ffffffffffffffff80821115612b7557600080fd5b908301906101a08286031215612b8a57600080fd5b612b926130ba565b612b9b8361281d565b8152612ba96020840161281d565b6020820152612bba6040840161281d565b6040820152612bcb6060840161281d565b6060820152612bdc6080840161281d565b6080820152612bed60a0840161281d565b60a082015260c0838101519082015260e0808401519082015261010080840151908201526101208084015190820152610140808401519082015261016080840151908201526101808084015183811115612c4657600080fd5b612c528882870161287e565b918301919091525095945050505050565b600080600060608486031215612c7857600080fd5b612c81846128d5565b9250612c8f602085016128d5565b9150604084015163ffffffff81168114612ca857600080fd5b809150509250925092565b600060208284031215612cc557600080fd5b5035919050565b600060208284031215612cde57600080fd5b5051919050565b600060208284031215612cf757600080fd5b611181826128f3565b60008060408385031215612d1357600080fd5b612d1c836128f3565b9150612a63602084016128f3565b600081518084526020808501945080840160005b83811015612d5a57815187529582019590820190600101612d3e565b509495945050505050565b60008151808452612d7d81602086016020860161324e565b601f01601f19169290920160200192915050565b60008251612da381846020870161324e565b9190910192915050565b60006001600160a01b038088168352808716602084015285604084015280851660608401525060a060808301526113d960a0830184612d65565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a060808301526113d960a0830184612d65565b6020815260006111816020830184612d2a565b6020815260006111816020830184612d65565b60208152612e616020820183516001600160a01b03169052565b60006020830151612e7d60408401826001600160a01b03169052565b5060408301516001600160a01b03811660608401525060608301516001600160a01b03811660808401525060808301516001600160a01b03811660a08401525060a08301516001600160a01b03811660c08401525060c083015160e08381019190915283015161010080840191909152830151610120808401919091528301516101408084019190915283015161016080840191909152830151610180808401919091528301516101a080840152611a856101c0840182612d65565b84815260606020808301829052908201849052600090859060808401835b87811015612f85578335612f6a816132f4565b6001600160a01b031682529282019290820190600101612f57565b508481036040860152612f988187612d2a565b9998505050505050505050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b81811015612ff55784516001600160a01b031683529383019391830191600101612fd0565b50506001600160a01b03969096166060850152505050608001529392505050565b8481528360208201526001600160a01b03831660408201526080606082015260006116036080830184612d65565b6000808335601e1984360301811261305b57600080fd5b83018035915067ffffffffffffffff82111561307657600080fd5b6020019150600581901b360382131561261f57600080fd5b60008235605e19833603018112612da357600080fd5b60008235609e19833603018112612da357600080fd5b6040516101a0810167ffffffffffffffff811182821017156130de576130de6132de565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561310d5761310d6132de565b604052919050565b600067ffffffffffffffff82111561312f5761312f6132de565b50601f01601f191660200190565b60008219821115613150576131506132b2565b500190565b60008261317257634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615613191576131916132b2565b500290565b6000828210156131a8576131a86132b2565b500390565b600060a082360312156131bf57600080fd5b60405160a0810167ffffffffffffffff82821081831117156131e3576131e36132de565b81604052843591506131f4826132f4565b8183526020850135602084015260408501359150613211826132f4565b81604084015260608501356060840152608085013591508082111561323557600080fd5b5061324236828601612828565b60808301525092915050565b60005b83811015613269578181015183820152602001613251565b838111156103e95750506000910152565b600060001982141561328e5761328e6132b2565b5060010190565b6000600160ff1b8214156132ab576132ab6132b2565b5060000390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146104d657600080fdfea164736f6c6343000807000a

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

000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000bd4a0f12293c54e4e8ad221271cf0d395dd60a71

-----Decoded View---------------
Arg [0] : _weth (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [1] : _treasury (address): 0xBD4a0F12293C54e4E8ad221271CF0d395dd60a71

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [1] : 000000000000000000000000bd4a0f12293c54e4e8ad221271cf0d395dd60a71


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
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.