ETH Price: $3,722.47 (-3.63%)

Contract

0x408EB3F5A578b3eEcFe2c0cD58988fAb306885b4

Overview

ETH Balance

0.010024834209936063 ETH

ETH Value

$37.32 (@ $3,722.47/ETH)
Transaction Hash
Method
Block
From
To
0x6404f8fe1216456302024-06-20 13:27:17172 days ago1718890037IN
0x408EB3F5...b306885b4
0.001429590542621 ETH0.0000192386140.22451864
0x6038ce651213851032024-06-14 12:43:03178 days ago1718368983IN
0x408EB3F5...b306885b4
0 ETH0.0000001269550.00041167
0x6404f8fe1213490732024-06-13 16:42:03179 days ago1718296923IN
0x408EB3F5...b306885b4
0 ETH0.0000004767520.00614333
0x6404f8fe1213489662024-06-13 16:38:29179 days ago1718296709IN
0x408EB3F5...b306885b4
0 ETH0.0000004783750.00590859
0x6038ce651213481352024-06-13 16:10:47179 days ago1718295047IN
0x408EB3F5...b306885b4
0 ETH0.0000011475870.00503995
0x6038ce651213477282024-06-13 15:57:13179 days ago1718294233IN
0x408EB3F5...b306885b4
0 ETH0.0000011324410.00513288
0x6038ce651213472662024-06-13 15:41:49179 days ago1718293309IN
0x408EB3F5...b306885b4
0.000289807926454 ETH0.0000011879840.00543139
0x6404f8fe1211957982024-06-10 3:32:53183 days ago1717990373IN
0x408EB3F5...b306885b4
0.000002709550322 ETH0.0000035204040.06054424
0x6404f8fe1211949212024-06-10 3:03:39183 days ago1717988619IN
0x408EB3F5...b306885b4
0.000002708324305 ETH0.0000035365780.06087947
0x6404f8fe1208219222024-06-01 11:50:21192 days ago1717242621IN
0x408EB3F5...b306885b4
0 ETH0.0000001276940.00268562
0x6404f8fe1206940772024-05-29 12:48:51194 days ago1716986931IN
0x408EB3F5...b306885b4
0.000026000904831 ETH0.0000034311380.0697993
0x6404f8fe1206063502024-05-27 12:04:37197 days ago1716811477IN
0x408EB3F5...b306885b4
0.000002565628949 ETH0.0000035884490.061013
0x6404f8fe1206063382024-05-27 12:04:13197 days ago1716811453IN
0x408EB3F5...b306885b4
0 ETH0.0000024583340.06073686
0x6038ce651203756072024-05-22 3:53:11202 days ago1716349991IN
0x408EB3F5...b306885b4
0 ETH0.0000105973840.06157811
0x6404f8fe1203515212024-05-21 14:30:19202 days ago1716301819IN
0x408EB3F5...b306885b4
0 ETH0.0000025250760.06161741
0x6404f8fe1199911662024-05-13 6:18:29211 days ago1715581109IN
0x408EB3F5...b306885b4
0 ETH0.0000024237850.0608871
0x6038ce651198723982024-05-10 12:19:33214 days ago1715343573IN
0x408EB3F5...b306885b4
0.000330005069882 ETH0.0000098646290.06093256
0x6038ce651198648542024-05-10 8:08:05214 days ago1715328485IN
0x408EB3F5...b306885b4
0 ETH0.0000140708350.06196542
0x6038ce651198638402024-05-10 7:34:17214 days ago1715326457IN
0x408EB3F5...b306885b4
0 ETH0.0000123946790.06060335
0x6038ce651198638122024-05-10 7:33:21214 days ago1715326401IN
0x408EB3F5...b306885b4
0 ETH0.0000123630930.0607623
0x6038ce651198635282024-05-10 7:23:53214 days ago1715325833IN
0x408EB3F5...b306885b4
0 ETH0.000012399290.06060551
0x6038ce651198635132024-05-10 7:23:23214 days ago1715325803IN
0x408EB3F5...b306885b4
0 ETH0.0000125830310.06150321
0x6404f8fe1198625792024-05-10 6:52:15214 days ago1715323935IN
0x408EB3F5...b306885b4
0.003941708309446 ETH0.0000035559370.06126429
0x6404f8fe1198625732024-05-10 6:52:03214 days ago1715323923IN
0x408EB3F5...b306885b4
0.003941708309446 ETH0.0000035746510.06157518
0x6038ce651198625452024-05-10 6:51:07214 days ago1715323867IN
0x408EB3F5...b306885b4
0 ETH0.0000118200420.06071509
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
1216456302024-06-20 13:27:17172 days ago1718890037
0x408EB3F5...b306885b4
0.001415436180813 ETH
1213472662024-06-13 15:41:49179 days ago1718293309
0x408EB3F5...b306885b4
0.000000289518408 ETH
1213472662024-06-13 15:41:49179 days ago1718293309
0x408EB3F5...b306885b4
0.000000289518408 ETH
1213472662024-06-13 15:41:49179 days ago1718293309
0x408EB3F5...b306885b4
0.000289807926454 ETH
1211957982024-06-10 3:32:53183 days ago1717990373
0x408EB3F5...b306885b4
0.000002709550322 ETH
1211949212024-06-10 3:03:39183 days ago1717988619
0x408EB3F5...b306885b4
0.000002708324305 ETH
1206063502024-05-27 12:04:37197 days ago1716811477
0x408EB3F5...b306885b4
0.000002565628949 ETH
1198723982024-05-10 12:19:33214 days ago1715343573
0x408EB3F5...b306885b4
0.000000232035258 ETH
1198723982024-05-10 12:19:33214 days ago1715343573
0x408EB3F5...b306885b4
0.000000232035258 ETH
1198723982024-05-10 12:19:33214 days ago1715343573
0x408EB3F5...b306885b4
0.000330005069882 ETH
1198648542024-05-10 8:08:05214 days ago1715328485
0x408EB3F5...b306885b4
0.00000000000447 ETH
1198648542024-05-10 8:08:05214 days ago1715328485
0x408EB3F5...b306885b4
0.00000000000447 ETH
1198638402024-05-10 7:34:17214 days ago1715326457
0x408EB3F5...b306885b4
0.00000000107974 ETH
1198638402024-05-10 7:34:17214 days ago1715326457
0x408EB3F5...b306885b4
0.00000000107974 ETH
1198638122024-05-10 7:33:21214 days ago1715326401
0x408EB3F5...b306885b4
0.00000000107974 ETH
1198638122024-05-10 7:33:21214 days ago1715326401
0x408EB3F5...b306885b4
0.00000000107974 ETH
1198635282024-05-10 7:23:53214 days ago1715325833
0x408EB3F5...b306885b4
0.000000001075659 ETH
1198635282024-05-10 7:23:53214 days ago1715325833
0x408EB3F5...b306885b4
0.000000001075659 ETH
1198635132024-05-10 7:23:23214 days ago1715325803
0x408EB3F5...b306885b4
0.000000001075659 ETH
1198635132024-05-10 7:23:23214 days ago1715325803
0x408EB3F5...b306885b4
0.000000001075659 ETH
1198625792024-05-10 6:52:15214 days ago1715323935
0x408EB3F5...b306885b4
0.000001294755366 ETH
1198625732024-05-10 6:52:03214 days ago1715323923
0x408EB3F5...b306885b4
0.000001294755366 ETH
1198625452024-05-10 6:51:07214 days ago1715323867
0x408EB3F5...b306885b4
0.000001300212941 ETH
1198625452024-05-10 6:51:07214 days ago1715323867
0x408EB3F5...b306885b4
0.000001300212941 ETH
1198625402024-05-10 6:50:57214 days ago1715323857
0x408EB3F5...b306885b4
0.000001300212941 ETH
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
YodlRouterV1

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Unlicense license

Contract Source Code (Solidity)

/**
 *Submitted for verification at optimistic.etherscan.io on 2023-09-01
*/

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

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

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

library TransferHelper {
    /// @notice Transfers tokens from the targeted address to the given destination
    /// @notice Errors with 'STF' if transfer fails
    /// @param token The contract address of the token to be transferred
    /// @param from The originating address from which the tokens will be transferred
    /// @param to The destination address of the transfer
    /// @param value The amount to be transferred
    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) =
            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
    }

    /// @notice Transfers tokens from msg.sender to a recipient
    /// @dev Errors with ST if transfer fails
    /// @param token The contract address of the token which will be transferred
    /// @param to The recipient of the transfer
    /// @param value The value of the transfer
    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
    }

    /// @notice Approves the stipulated contract to spend the given allowance in the given token
    /// @dev Errors with 'SA' if transfer fails
    /// @param token The contract address of the token to be approved
    /// @param to The target of the approval
    /// @param value The amount of the given token the target will be allowed to spend
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
    }

    /// @notice Transfers ETH to the recipient address
    /// @dev Fails with `STE`
    /// @param to The destination of the transfer
    /// @param value The value to be transferred
    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'STE');
    }
}

// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

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

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

interface AggregatorV3Interface {
  function decimals() external view returns (uint8);

  function description() external view returns (string memory);

  function version() external view returns (uint256);

  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
}

pragma abicoder v2;

/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
    /// @dev In the implementation you must pay the pool tokens owed for the swap.
    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata data
    ) external;
}

/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }

    /// @notice Swaps `amountIn` of one token for as much as possible of another token
    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
    /// @return amountOut The amount of the received token
    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);

    struct ExactInputParams {
        bytes path;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
    }

    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
    /// @return amountOut The amount of the received token
    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);

    struct ExactOutputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
        uint160 sqrtPriceLimitX96;
    }

    /// @notice Swaps as little as possible of one token for `amountOut` of another token
    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
    /// @return amountIn The amount of the input token
    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);

    struct ExactOutputParams {
        bytes path;
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
    }

    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
    /// @return amountIn The amount of the input token
    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}

// The Uniswap IWETH9 has an incompatible version. However, this is just an interface, so the version is irrelevant.
/// @title Interface for WETH9
interface IWETH9 is IERC20 {
    /// @notice Deposit ether to get wrapped ether
    function deposit() external payable;

    /// @notice Withdraw wrapped ether to get ether
    function withdraw(uint256) external;
}

interface ICurveRouter {
    function exchange_multiple(
        address[9] calldata _route,
        uint256[3][4] calldata _swap_params,
        uint256 _amount,
        uint256 _expected,
        address[4] calldata _pools,
        address _receiver
    ) external payable returns (uint256);
}

/// @title Yodl Router
/// @author YodlPay
/// @notice This contract facilitates payments for the yodl.me platform. It supports direct token payments
/// as well as payments using swaps through Uniswap and Curve. There is support for cross-currency payments
/// using Chainlink price feeds.
/// @dev Keep in mind when deploying that a IWETH9 compatible wrapped native token needs to be available on chain.
/// For Uniswap or Curve payments to work, there needs to be a valid router for each. The Curve router should support
/// the `exchange_multiple` method.
contract YodlRouterV1 is Ownable {
    enum SwapType {
        SINGLE,
        MULTI
    }

    /// @notice Parameters for a payment through Uniswap
    /// @dev The `returnRemainder` boolean determines if the excess token in should be returned to the user.
    struct YodlUniswapParams {
        address sender;
        address receiver;
        uint256 amountIn; // amount of tokenIn needed to satisfy amountOut
        uint256 amountOut; // The exact amount expected by merchant in tokenOut
        bytes32 memo;
        bytes path; // (address: tokenOut, uint24 poolfee, address: tokenIn) OR (address: tokenOut, uint24 poolfee2, address: tokenBase, uint24 poolfee1, tokenIn)
        address[2] priceFeeds;
        address extraFeeReceiver;
        uint256 extraFeeBps;
        bool returnRemainder;
        SwapType swapType;
    }

    /// @notice Parameters for a payment through Curve
    /// @dev The`route`, `swapParams` and `factoryAddresses` should be determined client-side by the CurveJS client.
    /// The `returnRemainder` boolean determines if the excess token out should be returned to the user.
    struct YodlCurveParams {
        address sender;
        address receiver;
        uint256 amountIn; // amount of tokenIn needed to satisfy amountOut
        // The exact amount expected by merchant in tokenOut
        // If we are using price feeds, this is in terms of the invoice amount, but it must have the same decimals as tokenOut
        uint256 amountOut;
        bytes32 memo;
        address[9] route;
        uint256[3][4] swapParams; // [i, j, swap_type] where i and j are the coin index for the n'th pool in route
        address[4] factoryAddresses;
        address[2] priceFeeds;
        address extraFeeReceiver;
        uint256 extraFeeBps;
        bool returnRemainder;
    }

    // This is not an actual token address, but we will use it to represent the native token in swaps
    address public constant NATIVE_TOKEN =
        0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
    uint256 public constant MAX_FEE_BPS = 5_000; // 50%

    address public feeTreasury;
    uint256 public baseFeeBps; // fee = calculateFee(amount, baseFeeDivisor)
    ISwapRouter public uniswapRouter;
    ICurveRouter public curveRouter;
    // Before deploying to a L2 with its own native token,
    // we should check that its wrapped native token works with IWETH9
    IWETH9 public wrappedNativeToken;
    string public version;

    /// @notice Emitted when a payment goes through
    /// @param sender The address who has made the payment
    /// @param receiver The address who has received the payment
    /// @param token The address of the token that was used for the payment. Either an ERC20 token or the native token
    /// address.
    /// @param amount The amount paid by the sender in terms of the token
    /// @param fees The fees taken by the Yodl router from the amount paid
    /// @param memo The message attached to the payment
    event Payment(
        address indexed sender,
        address indexed receiver,
        address token /* the token that payee receives, use address(0) for AVAX*/,
        uint256 amount,
        uint256 fees,
        bytes32 memo
    );

    /// @notice Emitted when a conversion has occured from one currency to another using a Chainlink price feed
    /// @param priceFeed The address of the price feed used for conversion
    /// @param exchangeRate The rate used from the price feed at the time of conversion
    event Convert(address indexed priceFeed, int256 exchangeRate);

    /// @notice Initializes the YodlRouter contract
    /// @dev Using an incorrect _wrappedNativeToken address will result in native token payments reverting
    /// @param _feeTreasury The address where we want the router to send fees. Can be a contract that supports receiving
    /// the native token or a regular address.
    /// @param _baseFeeBps The basis point amount as a whole number that we will take as a fee
    /// @param _version Version number of the contract
    /// @param _uniswapRouter The address of the Uniswap router, or address(0) if not supported
    /// @param _curveRouter The address of the Curve router, or address(0) if not supported
    /// @param _wrappedNativeToken The address of the IWETH9 compatible wrapped native token
    constructor(
        address _feeTreasury,
        uint256 _baseFeeBps,
        string memory _version,
        address _uniswapRouter,
        address _curveRouter,
        address _wrappedNativeToken
    ) {
        baseFeeBps = _baseFeeBps;
        feeTreasury = _feeTreasury;
        version = _version;
        uniswapRouter = ISwapRouter(_uniswapRouter);
        curveRouter = ICurveRouter(_curveRouter);
        wrappedNativeToken = IWETH9(_wrappedNativeToken);
    }

    /// @notice Enables the contract to receive Ether
    /// @dev We need a receive method for when we withdraw WETH to the router. It does not need to do anything.
    receive() external payable {}

    /**
     * @notice Handles payments when sending tokens directly without DEX.
     * ## Example: Pay without pricefeeds, e.g. USDC transfer
     *
     * payWithToken(
     *   "tx-123",         // memo
     *   5*10**18,         // 5$
     *   [0x0, 0x0],  // no pricefeeds
     *   0xUSDC,           // usdc token address
     *   0xAlice           // receiver token address
     * )
     *
     * ## Example: Pay with pricefeeds (EUR / USD)
     *
     * The user entered the amount in EUR, which gets converted into
     * USD by the on-chain pricefeed.
     *
     * payWithToken(
     *     "tx-123",               // memo
     *     4.5*10**18,             // 4.5 EUR (~5$).
     *     [0xEURUSD, 0x0],   // EUR/USD price feed
     *     0xUSDC,                 // usdc token address
     *     0xAlice                 // receiver token address
     * )
     *
     *
     * ## Example: Pay with extra fee
     *
     * 3rd parties can receive an extra fee that is taken directly from
     * the receivable amount.
     *
     * payWithToken(
     *     "tx-123",               // memo
     *     4.5*10**18,             // 4.5 EUR (~5$).
     *     [0xEURUSD, 0x0],   //
     *     0xUSDC,                 // usdc token address
     *     0xAlice,                // receiver token address
     *     0x3rdParty              // extra fee for 3rd party provider
     *     50,                    // extra fee bps 0.5%
     * )
     * @dev This is the most gas efficient payment method. It supports currency conversion using price feeds. The
     * native token (ETH, AVAX, MATIC) is represented by the NATIVE_TOKEN constant.
     * @param memo The message attached to the payment. If present, the router will take a fee.
     * @param amount The amount to pay before any price feeds are applied. This amount will be converted by the price
     * feeds and then the sender will pay the converted amount in the given token.
     * @param priceFeeds Array of Chainlink price feeds. See `exchangeRate` method for more details.
     * @param token Token address to be used for the payment. Either an ERC20 token or the native token address.
     * @param receiver Address to receive the payment
     * @param extraFeeReceiver Address to receive an extra fee that is taken from the payment amount
     * @param extraFeeBps Size of the extra fee in terms of basis points (or 0 for none)
     * @return Boolean representing whether the payment was successful
     */
    function payWithToken(
        bytes32 memo,
        uint256 amount,
        address[2] calldata priceFeeds,
        address token,
        address receiver,
        address extraFeeReceiver,
        uint256 extraFeeBps
    ) external payable returns (bool) {
        require(amount != 0, "invalid amount");

        // transform amount with priceFeeds
        if (priceFeeds[0] != address(0) || priceFeeds[1] != address(0)) {
            {
                int256[2] memory prices;
                address[2] memory priceFeedsUsed;
                (amount, priceFeedsUsed, prices) = exchangeRate(
                    priceFeeds,
                    amount
                );
                emit Convert(priceFeedsUsed[0], prices[0]);
                if (priceFeedsUsed[1] != address(0)) {
                    emit Convert(priceFeedsUsed[1], prices[1]);
                }
            }
        }

        if (token != NATIVE_TOKEN) {
            // ERC20 token
            require(
                IERC20(token).allowance(msg.sender, address(this)) >= amount,
                "insufficient allowance"
            );
        } else {
            // Native ether
            require(msg.value >= amount, "insufficient ether provided");
        }

        uint256 totalFee = 0;

        if (memo != "") {
            totalFee += transferFee(
                amount,
                baseFeeBps,
                token,
                token == NATIVE_TOKEN ? address(this) : msg.sender,
                feeTreasury
            );
        }

        if (extraFeeReceiver != address(0)) {
            // 50% maximum extra fee
            require(extraFeeBps < MAX_FEE_BPS, "extraFeeBps too high");

            totalFee += transferFee(
                amount,
                extraFeeBps,
                token,
                token == NATIVE_TOKEN ? address(this) : msg.sender,
                extraFeeReceiver
            );
        }

        // Transfer to receiver
        if (token != NATIVE_TOKEN) {
            // ERC20 token
            TransferHelper.safeTransferFrom(
                token,
                msg.sender,
                receiver,
                amount - totalFee
            );
        } else {
            // Native ether
            (bool success, ) = receiver.call{value: amount - totalFee}("");
            require(success, "transfer failed");
        }

        emit Payment(msg.sender, receiver, token, amount, totalFee, memo);

        return true;
    }

    /// @notice Handles a payment with a swap through Uniswap
    /// @dev This needs to have a valid Uniswap router or it will revert. Excess tokens from the swap as a result
    /// of slippage are in terms of the token in.
    /// @param params Struct that contains all the relevant parameters. See `YodlUniswapParams` for more details.
    /// @return The amount spent in terms of token in by Uniswap to complete this payment
    function payWithUniswap(
        YodlUniswapParams calldata params
    ) external payable returns (uint256) {
        require(
            address(uniswapRouter) != address(0),
            "uniswap router not present"
        );
        (address tokenOut, address tokenIn) = decodeTokenInTokenOut(
            params.path,
            params.swapType
        );
        uint256 amountSpent;

        // This is how much the recipient needs to receive
        uint256 amountOutExpected;
        if (
            params.priceFeeds[0] != address(0) ||
            params.priceFeeds[1] != address(0)
        ) {
            // Convert amountOut from invoice currency to swap currency using price feed
            int256[2] memory prices;
            address[2] memory priceFeeds;
            (amountOutExpected, priceFeeds, prices) = exchangeRate(
                params.priceFeeds,
                params.amountOut
            );
            emit Convert(priceFeeds[0], prices[0]);
            if (priceFeeds[1] != address(0)) {
                emit Convert(priceFeeds[1], prices[1]);
            }
        } else {
            amountOutExpected = params.amountOut;
        }

        // There should be no other situation in which we send a transaction with native token
        if (msg.value != 0) {
            // Wrap the native token
            require(
                msg.value >= params.amountIn,
                "insufficient ether provided"
            );
            wrappedNativeToken.deposit{value: params.amountIn}();

            // Update the tokenIn to wrapped native token
            // wrapped native token has the same number of decimals as native token
            tokenIn = address(wrappedNativeToken);
        } else {
            // Transfer the ERC20 token from the sender to the YodlRouter
            TransferHelper.safeTransferFrom(
                tokenIn,
                msg.sender,
                address(this),
                params.amountIn
            );
        }
        TransferHelper.safeApprove(
            tokenIn,
            address(uniswapRouter),
            params.amountIn
        );

        // Special case for when we want native token out
        bool useNativeToken = false;
        if (tokenOut == NATIVE_TOKEN) {
            useNativeToken = true;
            tokenOut = address(wrappedNativeToken);
        }

        if (params.swapType == SwapType.SINGLE) {
            uint24 poolFee = decodeSinglePoolFee(params.path);
            ISwapRouter.ExactOutputSingleParams
                memory routerParams = ISwapRouter.ExactOutputSingleParams({
                    tokenIn: tokenIn,
                    tokenOut: tokenOut,
                    fee: poolFee,
                    recipient: address(this),
                    deadline: block.timestamp,
                    amountOut: amountOutExpected,
                    amountInMaximum: params.amountIn,
                    sqrtPriceLimitX96: 0
                });

            amountSpent = uniswapRouter.exactOutputSingle(routerParams);
        } else {
            // We need to extract the path details so that we can use the tokenIn value from earlier which may have been replaced by WETH
            (, uint24 poolFee2, address tokenBase, uint24 poolFee1, ) = abi
                .decode(
                    params.path,
                    (address, uint24, address, uint24, address)
                );
            ISwapRouter.ExactOutputParams memory uniswapParams = ISwapRouter
                .ExactOutputParams({
                    path: abi.encodePacked(
                        tokenOut,
                        poolFee2,
                        tokenBase,
                        poolFee1,
                        tokenIn
                    ),
                    recipient: address(this),
                    deadline: block.timestamp,
                    amountOut: amountOutExpected,
                    amountInMaximum: params.amountIn
                });

            amountSpent = uniswapRouter.exactOutput(uniswapParams);
        }

        // Handle unwrapping wrapped native token
        if (useNativeToken) {
            // Unwrap and use NATIVE_TOKEN address as tokenOut
            IWETH9(wrappedNativeToken).withdraw(amountOutExpected);
            tokenOut = NATIVE_TOKEN;
        }

        // Calculate fee from amount out
        uint256 totalFee = 0;
        if (params.memo != "") {
            totalFee += calculateFee(amountOutExpected, baseFeeBps);
        }

        // Handle extra fees
        if (params.extraFeeReceiver != address(0)) {
            // 50% maximum extra fee
            require(params.extraFeeBps < MAX_FEE_BPS, "extraFee too high");

            totalFee += transferFee(
                amountOutExpected,
                params.extraFeeBps,
                tokenOut,
                address(this),
                params.extraFeeReceiver
            );
        }

        if (tokenOut == NATIVE_TOKEN) {
            (bool success, ) = params.receiver.call{
                value: amountOutExpected - totalFee
            }("");
            require(success, "transfer failed");
        } else {
            // transfer tokens to receiver
            TransferHelper.safeTransfer(
                tokenOut,
                params.receiver,
                amountOutExpected - totalFee
            );
        }

        emit Payment(
            params.sender,
            params.receiver,
            tokenOut,
            amountOutExpected,
            totalFee,
            params.memo
        );

        TransferHelper.safeApprove(tokenIn, address(uniswapRouter), 0);

        // For exact output swaps, the amountInMaximum may not have all been spent.
        // If the actual amount spent (amountIn) is less than the specified maximum amount, we must refund the msg.sender and approve the _uniswapRouter to spend 0.
        if (amountSpent < params.amountIn && params.returnRemainder == true) {
            uint256 remainder = params.amountIn - amountSpent;
            if (msg.value != 0) {
                // Unwrap wrapped native token and send to sender
                IWETH9(wrappedNativeToken).withdraw(remainder);
                (bool success, ) = params.sender.call{value: remainder}("");
                require(success, "transfer failed");
            } else {
                TransferHelper.safeTransfer(tokenIn, params.sender, remainder);
            }
        }

        return amountSpent;
    }

    /// @notice Handles a payment with a swap through Curve
    /// @dev This needs to have a valid Curve router or it will revert. Excess tokens from the swap as a result
    /// of slippage are in terms of the token out.
    /// @param params Struct that contains all the relevant parameters. See `YodlCurveParams` for more details.
    /// @return The amount received in terms of token out by the Curve swap
    function payWithCurve(
        YodlCurveParams calldata params
    ) external payable returns (uint256) {
        require(address(curveRouter) != address(0), "curve router not present");
        (address tokenOut, address tokenIn) = decodeTokenInTokenOutCurve(
            params.route
        );

        // This is how much the recipient needs to receive
        uint256 amountOutExpected;
        if (
            params.priceFeeds[0] != address(0) ||
            params.priceFeeds[1] != address(0)
        ) {
            // Convert amountOut from invoice currency to swap currency using price feed
            int256[2] memory prices;
            address[2] memory priceFeeds;
            (amountOutExpected, priceFeeds, prices) = exchangeRate(
                params.priceFeeds,
                params.amountOut
            );
            emit Convert(priceFeeds[0], prices[0]);
            if (priceFeeds[1] != address(0)) {
                emit Convert(priceFeeds[1], prices[1]);
            }
        } else {
            amountOutExpected = params.amountOut;
        }

        // There should be no other situation in which we send a transaction with native token
        if (msg.value != 0) {
            // Wrap the native token
            require(
                msg.value >= params.amountIn,
                "insufficient ether provided"
            );
            wrappedNativeToken.deposit{value: params.amountIn}();

            // Update the tokenIn to wrapped native token
            // wrapped native token has the same number of decimals as native token
            // wrapped native token is already the first token in the route parameter
            tokenIn = address(wrappedNativeToken);
        } else {
            // Transfer the ERC20 token from the sender to the YodlRouter
            TransferHelper.safeTransferFrom(
                tokenIn,
                msg.sender,
                address(this),
                params.amountIn
            );
        }
        TransferHelper.safeApprove(
            tokenIn,
            address(curveRouter),
            params.amountIn
        );

        // Make the swap - the YodlRouter will receive the tokens
        uint256 amountOut = curveRouter.exchange_multiple(
            params.route,
            params.swapParams,
            params.amountIn,
            amountOutExpected, // this will revert if we do not get at least this amount
            params.factoryAddresses, // this is for zap contracts
            address(this) // the Yodl router will receive the tokens
        );

        // Handle fees for the transaction - in terms out the token out
        uint256 totalFee = 0;
        if (params.memo != "") {
            totalFee += calculateFee(amountOutExpected, baseFeeBps);
        }

        // Handle extra fees
        if (params.extraFeeReceiver != address(0)) {
            // 50% maximum extra fee
            require(params.extraFeeBps < MAX_FEE_BPS, "extraFee too high");

            totalFee += transferFee(
                amountOutExpected,
                params.extraFeeBps,
                tokenOut,
                address(this),
                params.extraFeeReceiver
            );
        }

        if (tokenOut == NATIVE_TOKEN) {
            // Need to transfer native token to receiver
            (bool success, ) = params.receiver.call{
                value: amountOutExpected - totalFee
            }("");
            require(success, "transfer failed");
        } else {
            // Transfer tokens to receiver
            TransferHelper.safeTransfer(
                tokenOut,
                params.receiver,
                amountOutExpected - totalFee
            );
        }
        emit Payment(
            params.sender,
            params.receiver,
            tokenOut,
            amountOutExpected,
            totalFee,
            params.memo
        );

        uint256 remainder = amountOut - amountOutExpected;
        if (remainder > 0 && params.returnRemainder) {
            if (tokenOut == NATIVE_TOKEN) {
                // Transfer remainder native token to sender
                (bool success, ) = params.sender.call{value: remainder}("");
                require(success, "transfer failed");
            } else {
                // Return the additional token out amount to the sender
                TransferHelper.safeTransfer(tokenOut, params.sender, remainder);
            }
        }

        return amountOut;
    }

    /// @notice Transfers all fees or slippage collected by the router to the treasury address
    /// @param token The address of the token we want to transfer from the router
    function sweep(address token) external onlyOwner {
        if (token == NATIVE_TOKEN) {
            // transfer native token out of contract
            (bool success, ) = feeTreasury.call{value: address(this).balance}(
                ""
            );
            require(success, "transfer failed in sweep");
        } else {
            // transfer ERC20 contract
            TransferHelper.safeTransfer(
                token,
                feeTreasury,
                IERC20(token).balanceOf(address(this))
            );
        }
    }

    /**
     * @notice Calculates exchange rates from a given price feed
     * @dev At most we can have 2 price feeds.
     *
     * We will use a zero address to determine if we need to inverse a singular price feeds.
     *
     * For multiple price feeds, we will always pass them in such that we multiply by the first and divide by the second.
     * This works because all of our price feeds have USD as the quote currency.
     * @param priceFeeds Array of Chainlink price feeds
     * @param amount Amount to be converted by the price feed exchange rates
     * @return converted The amount after conversion
     * @return priceFeedsUsed The price feeds in the order they were used
     * @return prices The exchange rates from the price feeds
     */
    function exchangeRate(
        address[2] calldata priceFeeds,
        uint256 amount
    )
        public
        view
        returns (
            uint256 converted,
            address[2] memory priceFeedsUsed,
            int256[2] memory prices
        )
    {
        require(
            priceFeeds[0] != address(0) || priceFeeds[1] != address(0),
            "invalid pricefeeds"
        );

        bool shouldInverse;
        AggregatorV3Interface priceFeedOne;
        AggregatorV3Interface priceFeedTwo; // might not exist
        if (priceFeeds[0] == address(0)) {
            // Inverse the price feed
            shouldInverse = true;
            priceFeedOne = AggregatorV3Interface(priceFeeds[1]);
        } else {
            // No need to inverse
            priceFeedOne = AggregatorV3Interface(priceFeeds[0]);
            if (priceFeeds[1] != address(0)) {
                // Multiply by the first, divide by the second
                // Will always be A -> USD -> B
                priceFeedTwo = AggregatorV3Interface(priceFeeds[1]);
            }
        }

        // Calculate the converted value using price feeds
        uint256 decimals = uint256(10 ** uint256(priceFeedOne.decimals()));
        (, int256 price, , , ) = priceFeedOne.latestRoundData();
        prices[0] = price;
        if (shouldInverse) {
            converted = (amount * decimals) / uint256(price);
        } else {
            converted = (amount * uint256(price)) / decimals;
        }

        // We will always divide by the second price feed
        if (address(priceFeedTwo) != address(0)) {
            decimals = uint256(10 ** uint256(priceFeedTwo.decimals()));
            (, price, , , ) = priceFeedTwo.latestRoundData();
            prices[1] = price;
            converted = (converted * decimals) / uint256(price);
        }

        return (
            converted,
            [address(priceFeedOne), address(priceFeedTwo)],
            prices
        );
    }

    /// @notice Helper function to calculate fees
    /// @dev A basis point is 0.01% -> 1/10000 is one basis point
    /// So multiplying by the amount of basis points then dividing by 10000
    /// will give us the fee as a portion of the original amount, expressed in terms of basis points.
    ///
    /// Overflows are allowed to occur at ridiculously large amounts.
    /// @param amount The amount to calculate the fee for
    /// @param feeBps The size of the fee in terms of basis points
    /// @return The fee
    function calculateFee(
        uint256 amount,
        uint256 feeBps
    ) public pure returns (uint256) {
        return (amount * feeBps) / 10_000;
    }

    /// @notice Helper method to determine the token in and out from a Uniswap path
    /// @param path The path for a Uniswap swap
    /// @param swapType Enum for whether the swap is a single hop or multiple hop
    /// @return The tokenOut and tokenIn
    function decodeTokenInTokenOut(
        bytes memory path,
        SwapType swapType
    ) internal pure returns (address, address) {
        address tokenOut;
        address tokenIn;
        if (swapType == SwapType.SINGLE) {
            (tokenOut, , tokenIn) = abi.decode(
                path,
                (address, uint24, address)
            );
        } else {
            (tokenOut, , , , tokenIn) = abi.decode(
                path,
                (address, uint24, address, uint24, address)
            );
        }
        return (tokenOut, tokenIn);
    }

    /// @notice Helper method to get the fee for a single hop swap for Uniswap
    /// @param path The path for a Uniswap swap
    /// @return The pool fee for given swap path
    function decodeSinglePoolFee(
        bytes memory path
    ) internal pure returns (uint24) {
        (, uint24 poolFee, ) = abi.decode(path, (address, uint24, address));
        return poolFee;
    }

    /// @notice Helper method to determine the token in and out from a Curve route
    /// @param route Route for a Curve swap in the form of [token, pool address, token...] with zero addresses once the
    /// swap has completed
    /// @return The tokenOut and tokenIn
    function decodeTokenInTokenOutCurve(
        address[9] memory route
    ) internal pure returns (address, address) {
        address tokenIn = route[0];
        address tokenOut = route[2];
        // Output tokens can be located at indices 2, 4, 6 or 8, if the loop finds nothing, then it is index 2
        for (uint i = 4; i >= 2; i--) {
            if (route[i * 2] != address(0)) {
                tokenOut = route[i * 2];
                break;
            }
        }
        require(tokenOut != address(0), "Invalid route parameter");
        return (tokenOut, tokenIn);
    }

    /// @notice Calculates and transfers fee directly from an address to another
    /// @dev This can be used for directly transferring the Yodl fee from the sender to the treasury, or transferring
    /// the extra fee to the extra fee receiver.
    /// @param amount Amount from which to calculate the fee
    /// @param feeBps The size of the fee in basis points
    /// @param token The token which is being used to pay the fee. Can be an ERC20 token or the native token
    /// @param from The address from which we are transferring the fee
    /// @param to The address to which the fee will be sent
    /// @return The fee sent
    function transferFee(
        uint256 amount,
        uint256 feeBps,
        address token,
        address from,
        address to
    ) private returns (uint256) {
        uint256 fee = calculateFee(amount, feeBps);
        if (fee > 0) {
            if (token != NATIVE_TOKEN) {
                // ERC20 token
                if (from == address(this)) {
                    TransferHelper.safeTransfer(token, to, fee);
                } else {
                    // safeTransferFrom requires approval
                    TransferHelper.safeTransferFrom(token, from, to, fee);
                }
            } else {
                require(
                    from == address(this),
                    "can only transfer eth from the router address"
                );

                // Native ether
                (bool success, ) = to.call{value: fee}("");
                require(success, "transfer failed in transferFee");
            }
            return fee;
        } else {
            return 0;
        }
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_feeTreasury","type":"address"},{"internalType":"uint256","name":"_baseFeeBps","type":"uint256"},{"internalType":"string","name":"_version","type":"string"},{"internalType":"address","name":"_uniswapRouter","type":"address"},{"internalType":"address","name":"_curveRouter","type":"address"},{"internalType":"address","name":"_wrappedNativeToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"priceFeed","type":"address"},{"indexed":false,"internalType":"int256","name":"exchangeRate","type":"int256"}],"name":"Convert","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fees","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"memo","type":"bytes32"}],"name":"Payment","type":"event"},{"inputs":[],"name":"MAX_FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NATIVE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseFeeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"feeBps","type":"uint256"}],"name":"calculateFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"curveRouter","outputs":[{"internalType":"contract ICurveRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[2]","name":"priceFeeds","type":"address[2]"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"converted","type":"uint256"},{"internalType":"address[2]","name":"priceFeedsUsed","type":"address[2]"},{"internalType":"int256[2]","name":"prices","type":"int256[2]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bytes32","name":"memo","type":"bytes32"},{"internalType":"address[9]","name":"route","type":"address[9]"},{"internalType":"uint256[3][4]","name":"swapParams","type":"uint256[3][4]"},{"internalType":"address[4]","name":"factoryAddresses","type":"address[4]"},{"internalType":"address[2]","name":"priceFeeds","type":"address[2]"},{"internalType":"address","name":"extraFeeReceiver","type":"address"},{"internalType":"uint256","name":"extraFeeBps","type":"uint256"},{"internalType":"bool","name":"returnRemainder","type":"bool"}],"internalType":"struct YodlRouterV1.YodlCurveParams","name":"params","type":"tuple"}],"name":"payWithCurve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"memo","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address[2]","name":"priceFeeds","type":"address[2]"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"extraFeeReceiver","type":"address"},{"internalType":"uint256","name":"extraFeeBps","type":"uint256"}],"name":"payWithToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bytes32","name":"memo","type":"bytes32"},{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address[2]","name":"priceFeeds","type":"address[2]"},{"internalType":"address","name":"extraFeeReceiver","type":"address"},{"internalType":"uint256","name":"extraFeeBps","type":"uint256"},{"internalType":"bool","name":"returnRemainder","type":"bool"},{"internalType":"enum YodlRouterV1.SwapType","name":"swapType","type":"uint8"}],"internalType":"struct YodlRouterV1.YodlUniswapParams","name":"params","type":"tuple"}],"name":"payWithUniswap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wrappedNativeToken","outputs":[{"internalType":"contract IWETH9","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b5060405162002fde38038062002fde8339810160408190526200003491620001e5565b6200003f33620000bc565b6002859055600180546001600160a01b0319166001600160a01b0388161790558351620000749060069060208701906200010c565b50600380546001600160a01b039485166001600160a01b0319918216179091556004805493851693821693909317909255600580549190931691161790555062000354915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280546200011a9062000318565b90600052602060002090601f0160209004810192826200013e576000855562000189565b82601f106200015957805160ff191683800117855562000189565b8280016001018555821562000189579182015b82811115620001895782518255916020019190600101906200016c565b50620001979291506200019b565b5090565b5b808211156200019757600081556001016200019c565b80516001600160a01b0381168114620001ca57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c08789031215620001ff57600080fd5b6200020a87620001b2565b60208881015160408a01519298509650906001600160401b03808211156200023157600080fd5b818a0191508a601f8301126200024657600080fd5b8151818111156200025b576200025b620001cf565b604051601f8201601f19908116603f01168101908382118183101715620002865762000286620001cf565b816040528281528d868487010111156200029f57600080fd5b600093505b82841015620002c35784840186015181850187015292850192620002a4565b82841115620002d55760008684830101525b809950505050505050620002ec60608801620001b2565b9250620002fc60808801620001b2565b91506200030c60a08801620001b2565b90509295509295509295565b600181811c908216806200032d57607f821691505b6020821081036200034e57634e487b7160e01b600052602260045260246000fd5b50919050565b612c7a80620003646000396000f3fe6080604052600436106101025760003560e01c806360dc2340116100955780638da5cb5b116100645780638da5cb5b146102b6578063bf5a5940146102d4578063cda90b88146102ea578063d55be8c61461030a578063f2fde38b1461032057600080fd5b806360dc23401461023e5780636404f8fe1461025e578063715018a614610281578063735de9f71461029657600080fd5b806334e73122116100d157806334e73122146101c8578063534ce2a5146101f657806354fd4d50146102095780636038ce651461022b57600080fd5b806301681a621461010e5780630d742ff71461013057806317fcb39b1461016857806331f7d964146101a057600080fd5b3661010957005b600080fd5b34801561011a57600080fd5b5061012e6101293660046123a9565b610340565b005b34801561013c57600080fd5b5061015061014b3660046123de565b610496565b60405161015f93929190612409565b60405180910390f35b34801561017457600080fd5b50600554610188906001600160a01b031681565b6040516001600160a01b03909116815260200161015f565b3480156101ac57600080fd5b5061018873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156101d457600080fd5b506101e86101e3366004612473565b610808565b60405190815260200161015f565b6101e8610204366004612495565b61082a565b34801561021557600080fd5b5061021e610e22565b60405161015f919061250a565b6101e861023936600461251d565b610eb0565b34801561024a57600080fd5b50600154610188906001600160a01b031681565b61027161026c366004612559565b611809565b604051901515815260200161015f565b34801561028d57600080fd5b5061012e611c46565b3480156102a257600080fd5b50600354610188906001600160a01b031681565b3480156102c257600080fd5b506000546001600160a01b0316610188565b3480156102e057600080fd5b506101e860025481565b3480156102f657600080fd5b50600454610188906001600160a01b031681565b34801561031657600080fd5b506101e861138881565b34801561032c57600080fd5b5061012e61033b3660046123a9565b611c5a565b610348611cd0565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03821601610419576001546040516000916001600160a01b03169047908381818185875af1925050503d80600081146103ba576040519150601f19603f3d011682016040523d82523d6000602084013e6103bf565b606091505b50509050806104155760405162461bcd60e51b815260206004820152601860248201527f7472616e73666572206661696c656420696e207377656570000000000000000060448201526064015b60405180910390fd5b5050565b6001546040516370a0823160e01b81523060048201526104939183916001600160a01b03918216918316906370a0823190602401602060405180830381865afa15801561046a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048e91906125d4565b611d2a565b50565b60006104a0612376565b6104a8612376565b60006104b760208701876123a9565b6001600160a01b03161415806104e6575060006104da60408701602088016123a9565b6001600160a01b031614155b6105275760405162461bcd60e51b8152602060048201526012602482015271696e76616c6964207072696365666565647360701b604482015260640161040c565b600080808061053960208a018a6123a9565b6001600160a01b031603610562576001925061055b6040890160208a016123a9565b91506105a4565b61056f60208901896123a9565b9150600061058360408a0160208b016123a9565b6001600160a01b0316146105a4576105a16040890160208a016123a9565b90505b6000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106089190612603565b6106169060ff16600a612720565b90506000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610658573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067c919061274b565b5050509150508086600060028110610696576106966125ed565b602002015284156106bd57806106ac838b61279b565b6106b691906127ba565b97506106d5565b816106c8828b61279b565b6106d291906127ba565b97505b6001600160a01b038316156107de57826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107469190612603565b6107549060ff16600a612720565b9150826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610794573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b8919061274b565b5050506020880181905291508190506107d1838a61279b565b6107db91906127ba565b97505b5050604080518082019091526001600160a01b039283168152911660208201529250509250925092565b6000612710610817838561279b565b61082191906127ba565b90505b92915050565b6004546000906001600160a01b03166108855760405162461bcd60e51b815260206004820152601860248201527f637572766520726f75746572206e6f742070726573656e740000000000000000604482015260640161040c565b6000806108bd8460a0016009806020026040519081016040528092919082600960200280828437600092019190915250611e2a915050565b90925090506000806108d76103e087016103c088016123a9565b6001600160a01b0316141580610908575060006108fc61040087016103e088016123a9565b6001600160a01b031614155b156109b757610915612376565b61091d612376565b61092f876103c0018860600135610496565b815181516040519081529396509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b0316156109b057602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b50506109be565b5060608401355b3415610a695784604001353410156109e85760405162461bcd60e51b815260040161040c906127dc565b600560009054906101000a90046001600160a01b03166001600160a01b031663d0e30db086604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a3c57600080fd5b505af1158015610a50573d6000803e3d6000fd5b50506005546001600160a01b03169450610a7992505050565b610a798233308860400135611f0c565b600454610a959083906001600160a01b03166040880135612016565b6004805460408051630651cb3560e01b81526000936001600160a01b0390931692630651cb3592610adf9260a08c01926101c08d01928d01359189916103408f0191309101612849565b6020604051808303816000875af1158015610afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2291906125d4565b90506000608087013515610b4957610b3c83600254610808565b610b4690826128eb565b90505b6000610b5d61042089016104008a016123a9565b6001600160a01b031614610be55761138887610420013510610bb55760405162461bcd60e51b81526020600482015260116024820152700caf0e8e4c28ccaca40e8dede40d0d2ced607b1b604482015260640161040c565b610bd883610420890180359088903090610bd3906104008e016123a9565b61210f565b610be290826128eb565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03861601610c97576000610c1c6040890160208a016123a9565b6001600160a01b0316610c2f8386612903565b604051600081818185875af1925050503d8060008114610c6b576040519150601f19603f3d011682016040523d82523d6000602084013e610c70565b606091505b5050905080610c915760405162461bcd60e51b815260040161040c9061291a565b50610cb5565b610cb585610cab60408a0160208b016123a9565b61048e8487612903565b610cc560408801602089016123a9565b6001600160a01b0316610cdb60208901896123a9565b6001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac168786858c60800135604051610d1d9493929190612943565b60405180910390a36000610d318484612903565b9050600081118015610d505750610d5061046089016104408a01612977565b15610e165773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601610dff576000610d8960208a018a6123a9565b6001600160a01b03168260405160006040518083038185875af1925050503d8060008114610dd3576040519150601f19603f3d011682016040523d82523d6000602084013e610dd8565b606091505b5050905080610df95760405162461bcd60e51b815260040161040c9061291a565b50610e16565b610e1686610e1060208b018b6123a9565b83611d2a565b50909695505050505050565b60068054610e2f90612994565b80601f0160208091040260200160405190810160405280929190818152602001828054610e5b90612994565b8015610ea85780601f10610e7d57610100808354040283529160200191610ea8565b820191906000526020600020905b815481529060010190602001808311610e8b57829003601f168201915b505050505081565b6003546000906001600160a01b0316610f0b5760405162461bcd60e51b815260206004820152601a60248201527f756e697377617020726f75746572206e6f742070726573656e74000000000000604482015260640161040c565b600080610f6a610f1e60a08601866129c8565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610f659250505061018087016101608801612a0f565b61229d565b909250905060008080610f8360e0880160c089016123a9565b6001600160a01b0316141580610fb357506000610fa7610100880160e089016123a9565b6001600160a01b031614155b1561106157610fc0612376565b610fc8612376565b610fd98860c0018960600135610496565b815181516040519081529396509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b03161561105a57602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b5050611068565b5060608501355b34156111135785604001353410156110925760405162461bcd60e51b815260040161040c906127dc565b600560009054906101000a90046001600160a01b03166001600160a01b031663d0e30db087604001356040518263ffffffff1660e01b81526004016000604051808303818588803b1580156110e657600080fd5b505af11580156110fa573d6000803e3d6000fd5b50506005546001600160a01b0316955061112392505050565b6111238333308960400135611f0c565b60035461113f9084906001600160a01b03166040890135612016565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0386160161117857506005546001600160a01b0316935060015b600061118c61018089016101608a01612a0f565b600181111561119d5761119d612a30565b036113165760006111ee6111b460a08a018a6129c8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061230692505050565b60408051610100810182526001600160a01b038089168252898116602083015262ffffff84168284015230606083015242608083015260a082018790528b83013560c0830152600060e08301526003549251631b67c43360e31b8152939450909291169063db3e2198906112ca90849060040181516001600160a01b03908116825260208084015182169083015260408084015162ffffff16908301526060808401518216908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b6020604051808303816000875af11580156112e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130d91906125d4565b9450505061143b565b6000808061132760a08b018b6129c8565b8101906113349190612a57565b506040805160a0810182526bffffffffffffffffffffffff1960608f811b821660c08401526001600160e81b031960e888811b821660d486015287831b841660d786015286901b1660eb8401528e811b90911660ee830152825180830360e2018152610102830184528252306020830152428284015281018b90528f82013560808201526003549151631e51809360e31b81529498509296509094509092506001600160a01b03169063f28c0498906113f1908490600401612ac8565b6020604051808303816000875af1158015611410573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143491906125d4565b9650505050505b80156114b757600554604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561148757600080fd5b505af115801561149b573d6000803e3d6000fd5b5050505073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee94505b60006080880135156114dc576114cf83600254610808565b6114d990826128eb565b90505b60006114f06101208a016101008b016123a9565b6001600160a01b03161461157357611388886101200135106115485760405162461bcd60e51b81526020600482015260116024820152700caf0e8e4c28ccaca40e8dede40d0d2ced607b1b604482015260640161040c565b611566836101208a0180359089903090610bd3906101008f016123a9565b61157090826128eb565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038716016116255760006115aa60408a0160208b016123a9565b6001600160a01b03166115bd8386612903565b604051600081818185875af1925050503d80600081146115f9576040519150601f19603f3d011682016040523d82523d6000602084013e6115fe565b606091505b505090508061161f5760405162461bcd60e51b815260040161040c9061291a565b50611639565b61163986610cab60408b0160208c016123a9565b6116496040890160208a016123a9565b6001600160a01b031661165f60208a018a6123a9565b6001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac168886858d608001356040516116a19493929190612943565b60405180910390a36003546116c29086906001600160a01b03166000612016565b8760400135841080156116e857506116e261016089016101408a01612977565b15156001145b156117fd5760006116fd8560408b0135612903565b905034156117ea57600554604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561174b57600080fd5b505af115801561175f573d6000803e3d6000fd5b506000925061177491505060208b018b6123a9565b6001600160a01b03168260405160006040518083038185875af1925050503d80600081146117be576040519150601f19603f3d011682016040523d82523d6000602084013e6117c3565b606091505b50509050806117e45760405162461bcd60e51b815260040161040c9061291a565b506117fb565b6117fb86610e1060208c018c6123a9565b505b50919695505050505050565b60008660000361184c5760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b604482015260640161040c565b600061185b60208801886123a9565b6001600160a01b031614158061188a5750600061187e60408801602089016123a9565b6001600160a01b031614155b1561192d57611897612376565b61189f612376565b6118a9888a610496565b81518151604051908152939c509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b03161561192a57602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b50505b6001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611a0d57604051636eb1769f60e11b815233600482015230602482015287906001600160a01b0387169063dd62ed3e90604401602060405180830381865afa15801561199d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c191906125d4565b1015611a085760405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e7420616c6c6f77616e636560501b604482015260640161040c565b611a2d565b86341015611a2d5760405162461bcd60e51b815260040161040c906127dc565b60008815611a9057611a83886002548873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03168a6001600160a01b031614611a705733611a72565b305b6001546001600160a01b031661210f565b611a8d90826128eb565b90505b6001600160a01b03841615611b2c576113888310611ae75760405162461bcd60e51b81526020600482015260146024820152730caf0e8e4c28ccaca84e0e640e8dede40d0d2ced60631b604482015260640161040c565b611b1f8884886001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b175733611b19565b305b8861210f565b611b2990826128eb565b90505b6001600160a01b03861673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b6a57611b65863387611b60858d612903565b611f0c565b611be4565b60006001600160a01b038616611b80838b612903565b604051600081818185875af1925050503d8060008114611bbc576040519150601f19603f3d011682016040523d82523d6000602084013e611bc1565b606091505b5050905080611be25760405162461bcd60e51b815260040161040c9061291a565b505b846001600160a01b0316336001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac16888b858e604051611c2d9493929190612943565b60405180910390a360019150505b979650505050505050565b611c4e611cd0565b611c586000612326565b565b611c62611cd0565b6001600160a01b038116611cc75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161040c565b61049381612326565b6000546001600160a01b03163314611c585760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161040c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611d869190612b20565b6000604051808303816000865af19150503d8060008114611dc3576040519150601f19603f3d011682016040523d82523d6000602084013e611dc8565b606091505b5091509150818015611df2575080511580611df2575080806020019051810190611df29190612b3c565b611e235760405162461bcd60e51b815260206004820152600260248201526114d560f21b604482015260640161040c565b5050505050565b80516040820151600091829160045b60028110611eac57600086611e4f83600261279b565b60098110611e5f57611e5f6125ed565b60200201516001600160a01b031614611e9a5785611e7e82600261279b565b60098110611e8e57611e8e6125ed565b60200201519150611eac565b80611ea481612b59565b915050611e39565b506001600160a01b038116611f035760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420726f75746520706172616d65746572000000000000000000604482015260640161040c565b94909350915050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611f709190612b20565b6000604051808303816000865af19150503d8060008114611fad576040519150601f19603f3d011682016040523d82523d6000602084013e611fb2565b606091505b5091509150818015611fdc575080511580611fdc575080806020019051810190611fdc9190612b3c565b61200e5760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015260640161040c565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916120729190612b20565b6000604051808303816000865af19150503d80600081146120af576040519150601f19603f3d011682016040523d82523d6000602084013e6120b4565b606091505b50915091508180156120de5750805115806120de5750808060200190518101906120de9190612b3c565b611e235760405162461bcd60e51b8152602060048201526002602482015261534160f01b604482015260640161040c565b60008061211c8787610808565b9050801561228e576001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461217457306001600160a01b0385160361216857612163858483611d2a565b612287565b61216385858584611f0c565b6001600160a01b03841630146121e25760405162461bcd60e51b815260206004820152602d60248201527f63616e206f6e6c79207472616e73666572206574682066726f6d20746865207260448201526c6f75746572206164647265737360981b606482015260840161040c565b6000836001600160a01b03168260405160006040518083038185875af1925050503d806000811461222f576040519150601f19603f3d011682016040523d82523d6000602084013e612234565b606091505b50509050806122855760405162461bcd60e51b815260206004820152601e60248201527f7472616e73666572206661696c656420696e207472616e736665724665650000604482015260640161040c565b505b9050612294565b60009150505b95945050505050565b6000808080808560018111156122b5576122b5612a30565b036122db57858060200190518101906122ce9190612b70565b9193509091506122f99050565b858060200190518101906122ef9190612bbd565b9395509293505050505b90925090505b9250929050565b6000808280602001905181019061231d9190612b70565b50949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405180604001604052806002906020820280368337509192915050565b6001600160a01b038116811461049357600080fd5b6000602082840312156123bb57600080fd5b81356123c681612394565b9392505050565b806040810183101561082457600080fd5b600080606083850312156123f157600080fd5b6123fb84846123cd565b946040939093013593505050565b83815260a0810160208083018560005b600281101561243f5781516001600160a01b031683529183019190830190600101612419565b505050606083018460005b60028110156124675781518352918301919083019060010161244a565b50505050949350505050565b6000806040838503121561248657600080fd5b50508035926020909101359150565b600061046082840312156124a857600080fd5b50919050565b60005b838110156124c95781810151838201526020016124b1565b838111156124d8576000848401525b50505050565b600081518084526124f68160208601602086016124ae565b601f01601f19169290920160200192915050565b60208152600061082160208301846124de565b60006020828403121561252f57600080fd5b813567ffffffffffffffff81111561254657600080fd5b820161018081850312156123c657600080fd5b6000806000806000806000610100888a03121561257557600080fd5b873596506020880135955061258d8960408a016123cd565b9450608088013561259d81612394565b935060a08801356125ad81612394565b925060c08801356125bd81612394565b8092505060e0880135905092959891949750929550565b6000602082840312156125e657600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561261557600080fd5b815160ff811681146123c657600080fd5b634e487b7160e01b600052601160045260246000fd5b600181815b8085111561267757816000190482111561265d5761265d612626565b8085161561266a57918102915b93841c9390800290612641565b509250929050565b60008261268e57506001610824565b8161269b57506000610824565b81600181146126b157600281146126bb576126d7565b6001915050610824565b60ff8411156126cc576126cc612626565b50506001821b610824565b5060208310610133831016604e8410600b84101617156126fa575081810a610824565b612704838361263c565b806000190482111561271857612718612626565b029392505050565b6000610821838361267f565b805169ffffffffffffffffffff8116811461274657600080fd5b919050565b600080600080600060a0868803121561276357600080fd5b61276c8661272c565b945060208601519350604086015192506060860151915061278f6080870161272c565b90509295509295909350565b60008160001904831182151516156127b5576127b5612626565b500290565b6000826127d757634e487b7160e01b600052601260045260246000fd5b500490565b6020808252601b908201527f696e73756666696369656e742065746865722070726f76696465640000000000604082015260600190565b8060005b60048110156124d857813561282b81612394565b6001600160a01b031684526020938401939190910190600101612817565b610380810181886000805b600981101561288657823561286881612394565b6001600160a01b031684526020938401939290920191600101612854565b5061012085019250899150805b60048110156128b657606080848637938401828152939290920191600101612893565b50505050856102a0830152846102c08301526128d66102e0830185612813565b6001600160a01b038316610360830152611c3b565b600082198211156128fe576128fe612626565b500190565b60008282101561291557612915612626565b500390565b6020808252600f908201526e1d1c985b9cd9995c8819985a5b1959608a1b604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b801515811461049357600080fd5b60006020828403121561298957600080fd5b81356123c681612969565b600181811c908216806129a857607f821691505b6020821081036124a857634e487b7160e01b600052602260045260246000fd5b6000808335601e198436030181126129df57600080fd5b83018035915067ffffffffffffffff8211156129fa57600080fd5b6020019150368190038213156122ff57600080fd5b600060208284031215612a2157600080fd5b8135600281106123c657600080fd5b634e487b7160e01b600052602160045260246000fd5b62ffffff8116811461049357600080fd5b600080600080600060a08688031215612a6f57600080fd5b8535612a7a81612394565b94506020860135612a8a81612a46565b93506040860135612a9a81612394565b92506060860135612aaa81612a46565b91506080860135612aba81612394565b809150509295509295909350565b602081526000825160a06020840152612ae460c08401826124de565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b60008251612b328184602087016124ae565b9190910192915050565b600060208284031215612b4e57600080fd5b81516123c681612969565b600081612b6857612b68612626565b506000190190565b600080600060608486031215612b8557600080fd5b8351612b9081612394565b6020850151909350612ba181612a46565b6040850151909250612bb281612394565b809150509250925092565b600080600080600060a08688031215612bd557600080fd5b8551612be081612394565b6020870151909550612bf181612a46565b6040870151909450612c0281612394565b6060870151909350612c1381612a46565b6080870151909250612aba8161239456fe55f56a47af95f637819da860d955ff441e2d4c2a708c3608ead3781c68a63619a2646970667358221220fdfd1e319e66f69482d014c5ecc58850c9070303984da4fea86f3fb9f31af78464736f6c634300080d00330000000000000000000000005f0947253a8218894af13438ac2e2e0ced30d234000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156400000000000000000000000089287c32c2cac1c76227f6d300b2dbbab6b75c0800000000000000000000000042000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003302e320000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106101025760003560e01c806360dc2340116100955780638da5cb5b116100645780638da5cb5b146102b6578063bf5a5940146102d4578063cda90b88146102ea578063d55be8c61461030a578063f2fde38b1461032057600080fd5b806360dc23401461023e5780636404f8fe1461025e578063715018a614610281578063735de9f71461029657600080fd5b806334e73122116100d157806334e73122146101c8578063534ce2a5146101f657806354fd4d50146102095780636038ce651461022b57600080fd5b806301681a621461010e5780630d742ff71461013057806317fcb39b1461016857806331f7d964146101a057600080fd5b3661010957005b600080fd5b34801561011a57600080fd5b5061012e6101293660046123a9565b610340565b005b34801561013c57600080fd5b5061015061014b3660046123de565b610496565b60405161015f93929190612409565b60405180910390f35b34801561017457600080fd5b50600554610188906001600160a01b031681565b6040516001600160a01b03909116815260200161015f565b3480156101ac57600080fd5b5061018873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156101d457600080fd5b506101e86101e3366004612473565b610808565b60405190815260200161015f565b6101e8610204366004612495565b61082a565b34801561021557600080fd5b5061021e610e22565b60405161015f919061250a565b6101e861023936600461251d565b610eb0565b34801561024a57600080fd5b50600154610188906001600160a01b031681565b61027161026c366004612559565b611809565b604051901515815260200161015f565b34801561028d57600080fd5b5061012e611c46565b3480156102a257600080fd5b50600354610188906001600160a01b031681565b3480156102c257600080fd5b506000546001600160a01b0316610188565b3480156102e057600080fd5b506101e860025481565b3480156102f657600080fd5b50600454610188906001600160a01b031681565b34801561031657600080fd5b506101e861138881565b34801561032c57600080fd5b5061012e61033b3660046123a9565b611c5a565b610348611cd0565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03821601610419576001546040516000916001600160a01b03169047908381818185875af1925050503d80600081146103ba576040519150601f19603f3d011682016040523d82523d6000602084013e6103bf565b606091505b50509050806104155760405162461bcd60e51b815260206004820152601860248201527f7472616e73666572206661696c656420696e207377656570000000000000000060448201526064015b60405180910390fd5b5050565b6001546040516370a0823160e01b81523060048201526104939183916001600160a01b03918216918316906370a0823190602401602060405180830381865afa15801561046a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048e91906125d4565b611d2a565b50565b60006104a0612376565b6104a8612376565b60006104b760208701876123a9565b6001600160a01b03161415806104e6575060006104da60408701602088016123a9565b6001600160a01b031614155b6105275760405162461bcd60e51b8152602060048201526012602482015271696e76616c6964207072696365666565647360701b604482015260640161040c565b600080808061053960208a018a6123a9565b6001600160a01b031603610562576001925061055b6040890160208a016123a9565b91506105a4565b61056f60208901896123a9565b9150600061058360408a0160208b016123a9565b6001600160a01b0316146105a4576105a16040890160208a016123a9565b90505b6000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106089190612603565b6106169060ff16600a612720565b90506000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610658573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067c919061274b565b5050509150508086600060028110610696576106966125ed565b602002015284156106bd57806106ac838b61279b565b6106b691906127ba565b97506106d5565b816106c8828b61279b565b6106d291906127ba565b97505b6001600160a01b038316156107de57826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107469190612603565b6107549060ff16600a612720565b9150826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610794573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b8919061274b565b5050506020880181905291508190506107d1838a61279b565b6107db91906127ba565b97505b5050604080518082019091526001600160a01b039283168152911660208201529250509250925092565b6000612710610817838561279b565b61082191906127ba565b90505b92915050565b6004546000906001600160a01b03166108855760405162461bcd60e51b815260206004820152601860248201527f637572766520726f75746572206e6f742070726573656e740000000000000000604482015260640161040c565b6000806108bd8460a0016009806020026040519081016040528092919082600960200280828437600092019190915250611e2a915050565b90925090506000806108d76103e087016103c088016123a9565b6001600160a01b0316141580610908575060006108fc61040087016103e088016123a9565b6001600160a01b031614155b156109b757610915612376565b61091d612376565b61092f876103c0018860600135610496565b815181516040519081529396509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b0316156109b057602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b50506109be565b5060608401355b3415610a695784604001353410156109e85760405162461bcd60e51b815260040161040c906127dc565b600560009054906101000a90046001600160a01b03166001600160a01b031663d0e30db086604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a3c57600080fd5b505af1158015610a50573d6000803e3d6000fd5b50506005546001600160a01b03169450610a7992505050565b610a798233308860400135611f0c565b600454610a959083906001600160a01b03166040880135612016565b6004805460408051630651cb3560e01b81526000936001600160a01b0390931692630651cb3592610adf9260a08c01926101c08d01928d01359189916103408f0191309101612849565b6020604051808303816000875af1158015610afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2291906125d4565b90506000608087013515610b4957610b3c83600254610808565b610b4690826128eb565b90505b6000610b5d61042089016104008a016123a9565b6001600160a01b031614610be55761138887610420013510610bb55760405162461bcd60e51b81526020600482015260116024820152700caf0e8e4c28ccaca40e8dede40d0d2ced607b1b604482015260640161040c565b610bd883610420890180359088903090610bd3906104008e016123a9565b61210f565b610be290826128eb565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03861601610c97576000610c1c6040890160208a016123a9565b6001600160a01b0316610c2f8386612903565b604051600081818185875af1925050503d8060008114610c6b576040519150601f19603f3d011682016040523d82523d6000602084013e610c70565b606091505b5050905080610c915760405162461bcd60e51b815260040161040c9061291a565b50610cb5565b610cb585610cab60408a0160208b016123a9565b61048e8487612903565b610cc560408801602089016123a9565b6001600160a01b0316610cdb60208901896123a9565b6001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac168786858c60800135604051610d1d9493929190612943565b60405180910390a36000610d318484612903565b9050600081118015610d505750610d5061046089016104408a01612977565b15610e165773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601610dff576000610d8960208a018a6123a9565b6001600160a01b03168260405160006040518083038185875af1925050503d8060008114610dd3576040519150601f19603f3d011682016040523d82523d6000602084013e610dd8565b606091505b5050905080610df95760405162461bcd60e51b815260040161040c9061291a565b50610e16565b610e1686610e1060208b018b6123a9565b83611d2a565b50909695505050505050565b60068054610e2f90612994565b80601f0160208091040260200160405190810160405280929190818152602001828054610e5b90612994565b8015610ea85780601f10610e7d57610100808354040283529160200191610ea8565b820191906000526020600020905b815481529060010190602001808311610e8b57829003601f168201915b505050505081565b6003546000906001600160a01b0316610f0b5760405162461bcd60e51b815260206004820152601a60248201527f756e697377617020726f75746572206e6f742070726573656e74000000000000604482015260640161040c565b600080610f6a610f1e60a08601866129c8565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610f659250505061018087016101608801612a0f565b61229d565b909250905060008080610f8360e0880160c089016123a9565b6001600160a01b0316141580610fb357506000610fa7610100880160e089016123a9565b6001600160a01b031614155b1561106157610fc0612376565b610fc8612376565b610fd98860c0018960600135610496565b815181516040519081529396509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b03161561105a57602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b5050611068565b5060608501355b34156111135785604001353410156110925760405162461bcd60e51b815260040161040c906127dc565b600560009054906101000a90046001600160a01b03166001600160a01b031663d0e30db087604001356040518263ffffffff1660e01b81526004016000604051808303818588803b1580156110e657600080fd5b505af11580156110fa573d6000803e3d6000fd5b50506005546001600160a01b0316955061112392505050565b6111238333308960400135611f0c565b60035461113f9084906001600160a01b03166040890135612016565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0386160161117857506005546001600160a01b0316935060015b600061118c61018089016101608a01612a0f565b600181111561119d5761119d612a30565b036113165760006111ee6111b460a08a018a6129c8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061230692505050565b60408051610100810182526001600160a01b038089168252898116602083015262ffffff84168284015230606083015242608083015260a082018790528b83013560c0830152600060e08301526003549251631b67c43360e31b8152939450909291169063db3e2198906112ca90849060040181516001600160a01b03908116825260208084015182169083015260408084015162ffffff16908301526060808401518216908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b6020604051808303816000875af11580156112e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130d91906125d4565b9450505061143b565b6000808061132760a08b018b6129c8565b8101906113349190612a57565b506040805160a0810182526bffffffffffffffffffffffff1960608f811b821660c08401526001600160e81b031960e888811b821660d486015287831b841660d786015286901b1660eb8401528e811b90911660ee830152825180830360e2018152610102830184528252306020830152428284015281018b90528f82013560808201526003549151631e51809360e31b81529498509296509094509092506001600160a01b03169063f28c0498906113f1908490600401612ac8565b6020604051808303816000875af1158015611410573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143491906125d4565b9650505050505b80156114b757600554604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561148757600080fd5b505af115801561149b573d6000803e3d6000fd5b5050505073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee94505b60006080880135156114dc576114cf83600254610808565b6114d990826128eb565b90505b60006114f06101208a016101008b016123a9565b6001600160a01b03161461157357611388886101200135106115485760405162461bcd60e51b81526020600482015260116024820152700caf0e8e4c28ccaca40e8dede40d0d2ced607b1b604482015260640161040c565b611566836101208a0180359089903090610bd3906101008f016123a9565b61157090826128eb565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038716016116255760006115aa60408a0160208b016123a9565b6001600160a01b03166115bd8386612903565b604051600081818185875af1925050503d80600081146115f9576040519150601f19603f3d011682016040523d82523d6000602084013e6115fe565b606091505b505090508061161f5760405162461bcd60e51b815260040161040c9061291a565b50611639565b61163986610cab60408b0160208c016123a9565b6116496040890160208a016123a9565b6001600160a01b031661165f60208a018a6123a9565b6001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac168886858d608001356040516116a19493929190612943565b60405180910390a36003546116c29086906001600160a01b03166000612016565b8760400135841080156116e857506116e261016089016101408a01612977565b15156001145b156117fd5760006116fd8560408b0135612903565b905034156117ea57600554604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561174b57600080fd5b505af115801561175f573d6000803e3d6000fd5b506000925061177491505060208b018b6123a9565b6001600160a01b03168260405160006040518083038185875af1925050503d80600081146117be576040519150601f19603f3d011682016040523d82523d6000602084013e6117c3565b606091505b50509050806117e45760405162461bcd60e51b815260040161040c9061291a565b506117fb565b6117fb86610e1060208c018c6123a9565b505b50919695505050505050565b60008660000361184c5760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b604482015260640161040c565b600061185b60208801886123a9565b6001600160a01b031614158061188a5750600061187e60408801602089016123a9565b6001600160a01b031614155b1561192d57611897612376565b61189f612376565b6118a9888a610496565b81518151604051908152939c509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b03161561192a57602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b50505b6001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611a0d57604051636eb1769f60e11b815233600482015230602482015287906001600160a01b0387169063dd62ed3e90604401602060405180830381865afa15801561199d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c191906125d4565b1015611a085760405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e7420616c6c6f77616e636560501b604482015260640161040c565b611a2d565b86341015611a2d5760405162461bcd60e51b815260040161040c906127dc565b60008815611a9057611a83886002548873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03168a6001600160a01b031614611a705733611a72565b305b6001546001600160a01b031661210f565b611a8d90826128eb565b90505b6001600160a01b03841615611b2c576113888310611ae75760405162461bcd60e51b81526020600482015260146024820152730caf0e8e4c28ccaca84e0e640e8dede40d0d2ced60631b604482015260640161040c565b611b1f8884886001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b175733611b19565b305b8861210f565b611b2990826128eb565b90505b6001600160a01b03861673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b6a57611b65863387611b60858d612903565b611f0c565b611be4565b60006001600160a01b038616611b80838b612903565b604051600081818185875af1925050503d8060008114611bbc576040519150601f19603f3d011682016040523d82523d6000602084013e611bc1565b606091505b5050905080611be25760405162461bcd60e51b815260040161040c9061291a565b505b846001600160a01b0316336001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac16888b858e604051611c2d9493929190612943565b60405180910390a360019150505b979650505050505050565b611c4e611cd0565b611c586000612326565b565b611c62611cd0565b6001600160a01b038116611cc75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161040c565b61049381612326565b6000546001600160a01b03163314611c585760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161040c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611d869190612b20565b6000604051808303816000865af19150503d8060008114611dc3576040519150601f19603f3d011682016040523d82523d6000602084013e611dc8565b606091505b5091509150818015611df2575080511580611df2575080806020019051810190611df29190612b3c565b611e235760405162461bcd60e51b815260206004820152600260248201526114d560f21b604482015260640161040c565b5050505050565b80516040820151600091829160045b60028110611eac57600086611e4f83600261279b565b60098110611e5f57611e5f6125ed565b60200201516001600160a01b031614611e9a5785611e7e82600261279b565b60098110611e8e57611e8e6125ed565b60200201519150611eac565b80611ea481612b59565b915050611e39565b506001600160a01b038116611f035760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420726f75746520706172616d65746572000000000000000000604482015260640161040c565b94909350915050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611f709190612b20565b6000604051808303816000865af19150503d8060008114611fad576040519150601f19603f3d011682016040523d82523d6000602084013e611fb2565b606091505b5091509150818015611fdc575080511580611fdc575080806020019051810190611fdc9190612b3c565b61200e5760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015260640161040c565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916120729190612b20565b6000604051808303816000865af19150503d80600081146120af576040519150601f19603f3d011682016040523d82523d6000602084013e6120b4565b606091505b50915091508180156120de5750805115806120de5750808060200190518101906120de9190612b3c565b611e235760405162461bcd60e51b8152602060048201526002602482015261534160f01b604482015260640161040c565b60008061211c8787610808565b9050801561228e576001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461217457306001600160a01b0385160361216857612163858483611d2a565b612287565b61216385858584611f0c565b6001600160a01b03841630146121e25760405162461bcd60e51b815260206004820152602d60248201527f63616e206f6e6c79207472616e73666572206574682066726f6d20746865207260448201526c6f75746572206164647265737360981b606482015260840161040c565b6000836001600160a01b03168260405160006040518083038185875af1925050503d806000811461222f576040519150601f19603f3d011682016040523d82523d6000602084013e612234565b606091505b50509050806122855760405162461bcd60e51b815260206004820152601e60248201527f7472616e73666572206661696c656420696e207472616e736665724665650000604482015260640161040c565b505b9050612294565b60009150505b95945050505050565b6000808080808560018111156122b5576122b5612a30565b036122db57858060200190518101906122ce9190612b70565b9193509091506122f99050565b858060200190518101906122ef9190612bbd565b9395509293505050505b90925090505b9250929050565b6000808280602001905181019061231d9190612b70565b50949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405180604001604052806002906020820280368337509192915050565b6001600160a01b038116811461049357600080fd5b6000602082840312156123bb57600080fd5b81356123c681612394565b9392505050565b806040810183101561082457600080fd5b600080606083850312156123f157600080fd5b6123fb84846123cd565b946040939093013593505050565b83815260a0810160208083018560005b600281101561243f5781516001600160a01b031683529183019190830190600101612419565b505050606083018460005b60028110156124675781518352918301919083019060010161244a565b50505050949350505050565b6000806040838503121561248657600080fd5b50508035926020909101359150565b600061046082840312156124a857600080fd5b50919050565b60005b838110156124c95781810151838201526020016124b1565b838111156124d8576000848401525b50505050565b600081518084526124f68160208601602086016124ae565b601f01601f19169290920160200192915050565b60208152600061082160208301846124de565b60006020828403121561252f57600080fd5b813567ffffffffffffffff81111561254657600080fd5b820161018081850312156123c657600080fd5b6000806000806000806000610100888a03121561257557600080fd5b873596506020880135955061258d8960408a016123cd565b9450608088013561259d81612394565b935060a08801356125ad81612394565b925060c08801356125bd81612394565b8092505060e0880135905092959891949750929550565b6000602082840312156125e657600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561261557600080fd5b815160ff811681146123c657600080fd5b634e487b7160e01b600052601160045260246000fd5b600181815b8085111561267757816000190482111561265d5761265d612626565b8085161561266a57918102915b93841c9390800290612641565b509250929050565b60008261268e57506001610824565b8161269b57506000610824565b81600181146126b157600281146126bb576126d7565b6001915050610824565b60ff8411156126cc576126cc612626565b50506001821b610824565b5060208310610133831016604e8410600b84101617156126fa575081810a610824565b612704838361263c565b806000190482111561271857612718612626565b029392505050565b6000610821838361267f565b805169ffffffffffffffffffff8116811461274657600080fd5b919050565b600080600080600060a0868803121561276357600080fd5b61276c8661272c565b945060208601519350604086015192506060860151915061278f6080870161272c565b90509295509295909350565b60008160001904831182151516156127b5576127b5612626565b500290565b6000826127d757634e487b7160e01b600052601260045260246000fd5b500490565b6020808252601b908201527f696e73756666696369656e742065746865722070726f76696465640000000000604082015260600190565b8060005b60048110156124d857813561282b81612394565b6001600160a01b031684526020938401939190910190600101612817565b610380810181886000805b600981101561288657823561286881612394565b6001600160a01b031684526020938401939290920191600101612854565b5061012085019250899150805b60048110156128b657606080848637938401828152939290920191600101612893565b50505050856102a0830152846102c08301526128d66102e0830185612813565b6001600160a01b038316610360830152611c3b565b600082198211156128fe576128fe612626565b500190565b60008282101561291557612915612626565b500390565b6020808252600f908201526e1d1c985b9cd9995c8819985a5b1959608a1b604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b801515811461049357600080fd5b60006020828403121561298957600080fd5b81356123c681612969565b600181811c908216806129a857607f821691505b6020821081036124a857634e487b7160e01b600052602260045260246000fd5b6000808335601e198436030181126129df57600080fd5b83018035915067ffffffffffffffff8211156129fa57600080fd5b6020019150368190038213156122ff57600080fd5b600060208284031215612a2157600080fd5b8135600281106123c657600080fd5b634e487b7160e01b600052602160045260246000fd5b62ffffff8116811461049357600080fd5b600080600080600060a08688031215612a6f57600080fd5b8535612a7a81612394565b94506020860135612a8a81612a46565b93506040860135612a9a81612394565b92506060860135612aaa81612a46565b91506080860135612aba81612394565b809150509295509295909350565b602081526000825160a06020840152612ae460c08401826124de565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b60008251612b328184602087016124ae565b9190910192915050565b600060208284031215612b4e57600080fd5b81516123c681612969565b600081612b6857612b68612626565b506000190190565b600080600060608486031215612b8557600080fd5b8351612b9081612394565b6020850151909350612ba181612a46565b6040850151909250612bb281612394565b809150509250925092565b600080600080600060a08688031215612bd557600080fd5b8551612be081612394565b6020870151909550612bf181612a46565b6040870151909450612c0281612394565b6060870151909350612c1381612a46565b6080870151909250612aba8161239456fe55f56a47af95f637819da860d955ff441e2d4c2a708c3608ead3781c68a63619a2646970667358221220fdfd1e319e66f69482d014c5ecc58850c9070303984da4fea86f3fb9f31af78464736f6c634300080d0033

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

0000000000000000000000005f0947253a8218894af13438ac2e2e0ced30d234000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156400000000000000000000000089287c32c2cac1c76227f6d300b2dbbab6b75c0800000000000000000000000042000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003302e320000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _feeTreasury (address): 0x5f0947253a8218894af13438ac2e2E0CeD30d234
Arg [1] : _baseFeeBps (uint256): 20
Arg [2] : _version (string): 0.2
Arg [3] : _uniswapRouter (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
Arg [4] : _curveRouter (address): 0x89287c32c2CAC1C76227F6d300B2DBbab6b75C08
Arg [5] : _wrappedNativeToken (address): 0x4200000000000000000000000000000000000006

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000005f0947253a8218894af13438ac2e2e0ced30d234
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [3] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Arg [4] : 00000000000000000000000089287c32c2cac1c76227f6d300b2dbbab6b75c08
Arg [5] : 0000000000000000000000004200000000000000000000000000000000000006
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [7] : 302e320000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

14512:30430:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37016:561;;;;;;;;;;-1:-1:-1;37016:561:0;;;;;:::i;:::-;;:::i;:::-;;38359:2034;;;;;;;;;;-1:-1:-1;38359:2034:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;16951:32;;;;;;;;;;-1:-1:-1;16951:32:0;;;;-1:-1:-1;;;;;16951:32:0;;;;;;-1:-1:-1;;;;;2127:32:1;;;2109:51;;2097:2;2082:18;16951:32:0;1949:217:1;16475:90:0;;;;;;;;;;;;16523:42;16475:90;;40931:161;;;;;;;;;;-1:-1:-1;40931:161:0;;;;;:::i;:::-;;:::i;:::-;;;2778:25:1;;;2766:2;2751:18;40931:161:0;2632:177:1;32225:4604:0;;;;;;:::i;:::-;;:::i;16990:21::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;25140:6661::-;;;;;;:::i;:::-;;:::i;16631:26::-;;;;;;;;;;-1:-1:-1;16631:26:0;;;;-1:-1:-1;;;;;16631:26:0;;;22134:2563;;;;;;:::i;:::-;;:::i;:::-;;;5204:14:1;;5197:22;5179:41;;5167:2;5152:18;22134:2563:0;5039:187:1;7929:103:0;;;;;;;;;;;;;:::i;16742:32::-;;;;;;;;;;-1:-1:-1;16742:32:0;;;;-1:-1:-1;;;;;16742:32:0;;;7281:87;;;;;;;;;;-1:-1:-1;7327:7:0;7354:6;-1:-1:-1;;;;;7354:6:0;7281:87;;16664:25;;;;;;;;;;;;;;;;16781:31;;;;;;;;;;-1:-1:-1;16781:31:0;;;;-1:-1:-1;;;;;16781:31:0;;;16572:43;;;;;;;;;;;;16610:5;16572:43;;8187:201;;;;;;;;;;-1:-1:-1;8187:201:0;;;;;:::i;:::-;;:::i;37016:561::-;7167:13;:11;:13::i;:::-;-1:-1:-1;;;;;;;37080:21:0;::::1;::::0;37076:494:::1;;37191:11;::::0;:82:::1;::::0;37173:12:::1;::::0;-1:-1:-1;;;;;37191:11:0::1;::::0;37215:21:::1;::::0;37173:12;37191:82;37173:12;37191:82;37215:21;37191:11;:82:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37172:101;;;37296:7;37288:44;;;::::0;-1:-1:-1;;;37288:44:0;;6098:2:1;37288:44:0::1;::::0;::::1;6080:21:1::0;6137:2;6117:18;;;6110:30;6176:26;6156:18;;;6149:54;6220:18;;37288:44:0::1;;;;;;;;;37103:241;37016:561:::0;:::o;37076:494::-:1;37475:11;::::0;37505:38:::1;::::0;-1:-1:-1;;;37505:38:0;;37537:4:::1;37505:38;::::0;::::1;2109:51:1::0;37405:153:0::1;::::0;37451:5;;-1:-1:-1;;;;;37475:11:0;;::::1;::::0;37505:23;::::1;::::0;::::1;::::0;2082:18:1;;37505:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37405:27;:153::i;:::-;37016:561:::0;:::o;38359:2034::-;38516:17;38548:32;;:::i;:::-;38595:23;;:::i;:::-;38693:1;38668:13;;;;:10;:13;:::i;:::-;-1:-1:-1;;;;;38668:27:0;;;:58;;;-1:-1:-1;38724:1:0;38699:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;38699:27:0;;;38668:58;38646:126;;;;-1:-1:-1;;;38646:126:0;;6772:2:1;38646:126:0;;;6754:21:1;6811:2;6791:18;;;6784:30;-1:-1:-1;;;6830:18:1;;;6823:48;6888:18;;38646:126:0;6570:342:1;38646:126:0;38785:18;;;;38927:13;;;;:10;:13;:::i;:::-;-1:-1:-1;;;;;38927:27:0;;38923:550;;39026:4;;-1:-1:-1;39082:13:0;;;;;;;;:::i;:::-;39045:51;;38923:550;;;39201:13;;;;:10;:13;:::i;:::-;39164:51;-1:-1:-1;39259:1:0;39234:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;39234:27:0;;39230:232;;39432:13;;;;;;;;:::i;:::-;39395:51;;39230:232;39545:16;39586:12;-1:-1:-1;;;;;39586:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39572:38;;39578:32;;39572:2;:38;:::i;:::-;39545:66;;39625:12;39647;-1:-1:-1;;;;;39647:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39622:55;;;;;;39700:5;39688:6;39695:1;39688:9;;;;;;;:::i;:::-;;;;:17;39716:175;;;;39792:5;39763:17;39772:8;39763:6;:17;:::i;:::-;39762:36;;;;:::i;:::-;39750:48;;39716:175;;;39871:8;39844:23;39861:5;39844:6;:23;:::i;:::-;39843:36;;;;:::i;:::-;39831:48;;39716:175;-1:-1:-1;;;;;39966:35:0;;;39962:287;;40051:12;-1:-1:-1;;;;;40051:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40037:38;;40043:32;;40037:2;:38;:::i;:::-;40018:58;;40109:12;-1:-1:-1;;;;;40109:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;40154:9:0;;;:17;;;40091:48;-1:-1:-1;40091:48:0;;-1:-1:-1;40199:20:0;40211:8;40199:9;:20;:::i;:::-;40198:39;;;;:::i;:::-;40186:51;;39962:287;-1:-1:-1;;40261:124:0;;;;;;;;;-1:-1:-1;;;;;40261:124:0;;;;;;;;;;;;-1:-1:-1;;38359:2034:0;;;;;:::o;40931:161::-;41031:7;41078:6;41059:15;41068:6;41059;:15;:::i;:::-;41058:26;;;;:::i;:::-;41051:33;;40931:161;;;;;:::o;32225:4604::-;32358:11;;32322:7;;-1:-1:-1;;;;;32358:11:0;32342:71;;;;-1:-1:-1;;;32342:71:0;;9960:2:1;32342:71:0;;;9942:21:1;9999:2;9979:18;;;9972:30;10038:26;10018:18;;;10011:54;10082:18;;32342:71:0;9758:348:1;32342:71:0;32425:16;32443:15;32462:64;32503:6;:12;;32462:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32462:26:0;;-1:-1:-1;;32462:64:0:i;:::-;32424:102;;-1:-1:-1;32424:102:0;-1:-1:-1;32599:25:0;;32653:20;;;;:17;;;:20;:::i;:::-;-1:-1:-1;;;;;32653:34:0;;;:85;;;-1:-1:-1;32736:1:0;32704:20;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32704:34:0;;;32653:85;32635:695;;;32855:23;;:::i;:::-;32893:28;;:::i;:::-;32978:98;33009:6;:17;;33045:6;:16;;;32978:12;:98::i;:::-;33104:13;;33119:9;;33096:33;;2778:25:1;;;32936:140:0;;-1:-1:-1;32936:140:0;;-1:-1:-1;32936:140:0;;-1:-1:-1;;;;;;33096:33:0;;-1:-1:-1;;;;;;;;;;;33096:33:0;33104:13;2751:18:1;33096:33:0;;;;;;;33148:13;;;;-1:-1:-1;;;;;33148:27:0;;33144:106;;33209:13;;;;;33224:9;;;;33201:33;;2778:25:1;;;-1:-1:-1;;;;;33201:33:0;;;;-1:-1:-1;;;;;;;;;;;33201:33:0;2751:18:1;33201:33:0;;;;;;;33144:106;32750:511;;32635:695;;;-1:-1:-1;33302:16:0;;;;32635:695;33442:9;:14;33438:829;;33550:6;:15;;;33537:9;:28;;33511:117;;;;-1:-1:-1;;;33511:117:0;;;;;;;:::i;:::-;33643:18;;;;;;;;;-1:-1:-1;;;;;33643:18:0;-1:-1:-1;;;;;33643:26:0;;33677:6;:15;;;33643:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;33961:18:0;;-1:-1:-1;;;;;33961:18:0;;-1:-1:-1;33438:829:0;;-1:-1:-1;;;33438:829:0;;34088:167;34138:7;34164:10;34201:4;34225:6;:15;;;34088:31;:167::i;:::-;34348:11;;34277:124;;34318:7;;-1:-1:-1;;;;;34348:11:0;34375:15;;;;34277:26;:124::i;:::-;34501:11;;;34604:15;34501:357;;-1:-1:-1;;;34501:357:0;;34481:17;;-1:-1:-1;;;;;34501:11:0;;;;:29;;:357;;34545:12;;;;34572:17;;;;34604:15;;;;34634:17;;34724:23;;;;34799:4;;34501:357;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34481:377;-1:-1:-1;34944:16:0;34979:11;;;;:17;34975:105;;35025:43;35038:17;35057:10;;35025:12;:43::i;:::-;35013:55;;;;:::i;:::-;;;34975:105;35161:1;35126:23;;;;;;;;:::i;:::-;-1:-1:-1;;;;;35126:37:0;;35122:399;;16610:5;35226:6;:18;;;:32;35218:62;;;;-1:-1:-1;;;35218:62:0;;12963:2:1;35218:62:0;;;12945:21:1;13002:2;12982:18;;;12975:30;-1:-1:-1;;;13021:18:1;;;13014:47;13078:18;;35218:62:0;12761:341:1;35218:62:0;35309:200;35339:17;35375:18;;;;;;35412:8;;35447:4;;35471:23;;;;;;:::i;:::-;35309:11;:200::i;:::-;35297:212;;;;:::i;:::-;;;35122:399;-1:-1:-1;;;;;;;35537:24:0;;;35533:504;;35637:12;35655:15;;;;;;;;:::i;:::-;-1:-1:-1;;;;;35655:20:0;35701:28;35721:8;35701:17;:28;:::i;:::-;35655:93;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35636:112;;;35771:7;35763:35;;;;-1:-1:-1;;;35763:35:0;;;;;;;:::i;:::-;35563:247;35533:504;;;35875:150;35921:8;35948:15;;;;;;;;:::i;:::-;35982:28;36002:8;35982:17;:28;:::i;35875:150::-;36102:15;;;;;;;;:::i;:::-;-1:-1:-1;;;;;36052:180:0;36074:13;;;;:6;:13;:::i;:::-;-1:-1:-1;;;;;36052:180:0;;36132:8;36155:17;36187:8;36210:6;:11;;;36052:180;;;;;;;;;:::i;:::-;;;;;;;;36245:17;36265:29;36277:17;36265:9;:29;:::i;:::-;36245:49;;36321:1;36309:9;:13;:39;;;;-1:-1:-1;36326:22:0;;;;;;;;:::i;:::-;36305:488;;;-1:-1:-1;;;;;;;36369:24:0;;;36365:417;;36477:12;36495:13;;;;:6;:13;:::i;:::-;-1:-1:-1;;;;;36495:18:0;36521:9;36495:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36476:59;;;36562:7;36554:35;;;;-1:-1:-1;;;36554:35:0;;;;;;;:::i;:::-;36395:210;36365:417;;;36703:63;36731:8;36741:13;;;;:6;:13;:::i;:::-;36756:9;36703:27;:63::i;:::-;-1:-1:-1;36812:9:0;;32225:4604;-1:-1:-1;;;;;;32225:4604:0:o;16990:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;25140:6661::-;25291:13;;25241:7;;-1:-1:-1;;;;;25291:13:0;25261:112;;;;-1:-1:-1;;;25261:112:0;;14959:2:1;25261:112:0;;;14941:21:1;14998:2;14978:18;;;14971:30;15037:28;15017:18;;;15010:56;15083:18;;25261:112:0;14757:350:1;25261:112:0;25385:16;;25422:88;25458:11;;;;:6;:11;:::i;:::-;25422:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;25484:15:0;;-1:-1:-1;;;25484:15:0;;;;;;;:::i;:::-;25422:21;:88::i;:::-;25384:126;;-1:-1:-1;25384:126:0;-1:-1:-1;25521:19:0;;;25667:20;;;;:17;;;:20;:::i;:::-;-1:-1:-1;;;;;25667:34:0;;;:85;;;-1:-1:-1;25750:1:0;25718:20;;;;;;;;:::i;:::-;-1:-1:-1;;;;;25718:34:0;;;25667:85;25649:695;;;25869:23;;:::i;:::-;25907:28;;:::i;:::-;25992:98;26023:6;:17;;26059:6;:16;;;25992:12;:98::i;:::-;26118:13;;26133:9;;26110:33;;2778:25:1;;;25950:140:0;;-1:-1:-1;25950:140:0;;-1:-1:-1;25950:140:0;;-1:-1:-1;;;;;;26110:33:0;;-1:-1:-1;;;;;;;;;;;26110:33:0;26118:13;2751:18:1;26110:33:0;;;;;;;26162:13;;;;-1:-1:-1;;;;;26162:27:0;;26158:106;;26223:13;;;;;26238:9;;;;26215:33;;2778:25:1;;;-1:-1:-1;;;;;26215:33:0;;;;-1:-1:-1;;;;;;;;;;;26215:33:0;2751:18:1;26215:33:0;;;;;;;26158:106;25764:511;;25649:695;;;-1:-1:-1;26316:16:0;;;;25649:695;26456:9;:14;26452:742;;26564:6;:15;;;26551:9;:28;;26525:117;;;;-1:-1:-1;;;26525:117:0;;;;;;;:::i;:::-;26657:18;;;;;;;;;-1:-1:-1;;;;;26657:18:0;-1:-1:-1;;;;;26657:26:0;;26691:6;:15;;;26657:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;26888:18:0;;-1:-1:-1;;;;;26888:18:0;;-1:-1:-1;26452:742:0;;-1:-1:-1;;;26452:742:0;;27015:167;27065:7;27091:10;27128:4;27152:6;:15;;;27015:31;:167::i;:::-;27275:13;;27204:126;;27245:7;;-1:-1:-1;;;;;27275:13:0;27304:15;;;;27204:26;:126::i;:::-;27402:19;-1:-1:-1;;;;;;;27444:24:0;;;27440:131;;-1:-1:-1;27540:18:0;;-1:-1:-1;;;;;27540:18:0;;-1:-1:-1;27502:4:0;27440:131;27606:15;27587;;;;;;;;:::i;:::-;:34;;;;;;;;:::i;:::-;;27583:1727;;27638:14;27655:32;27675:11;;;;:6;:11;:::i;:::-;27655:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27655:19:0;;-1:-1:-1;;;27655:32:0:i;:::-;27777:415;;;;;;;;-1:-1:-1;;;;;27777:415:0;;;;;;;;;;;;;;;;;;;27970:4;27777:415;;;;28008:15;27777:415;;;;;;;;;;28114:15;;;;27777:415;;;;27702:72;27777:415;;;;28223:13;;:45;;-1:-1:-1;;;28223:45:0;;27638:49;;-1:-1:-1;27777:415:0;;28223:13;;;:31;;:45;;27777:415;;28223:45;;16330:13:1;;-1:-1:-1;;;;;16326:22:1;;;16308:41;;16409:4;16397:17;;;16391:24;16387:33;;16365:20;;;16358:63;16481:4;16469:17;;;16463:24;16489:8;16459:39;16437:20;;;16430:69;16559:4;16547:17;;;16541:24;16537:33;;16515:20;;;16508:63;16627:4;16615:17;;;16609:24;16587:20;;;16580:54;16288:3;16678:17;;;16672:24;16650:20;;;16643:54;16753:4;16741:17;;;16735:24;16713:20;;;16706:54;16820:4;16808:17;;;16802:24;16798:33;16776:20;;;16769:63;;;;16257:3;16242:19;;16043:795;28223:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28209:59;;27623:657;;27583:1727;;;28443:15;;;28551:11;;;;:6;:11;:::i;:::-;28500:147;;;;;;;:::i;:::-;-1:-1:-1;28715:512:0;;;;;;;;-1:-1:-1;;18112:2:1;18108:15;;;18104:24;;28792:214:0;;;18092:37:1;-1:-1:-1;;;;;;18152:3:1;18200:16;;;18196:25;;18182:12;;;18175:47;18256:15;;;18252:24;;18238:12;;;18231:46;18311:16;;;18307:25;18293:12;;;18286:47;18367:15;;;18363:24;;;18349:12;;;18342:46;28792:214:0;;;;;;;;;18404:12:1;;;28792:214:0;;28715:512;;29048:4;28792:214;28715:512;;;29086:15;28715:512;;;;;;;;;29192:15;;;;28715:512;;;;29258:13;;:40;;-1:-1:-1;;;29258:40:0;;18200:16:1;;-1:-1:-1;18256:15:1;;-1:-1:-1;18311:16:1;;-1:-1:-1;28715:512:0;;-1:-1:-1;;;;;;29258:13:0;;:25;;:40;;28715:512;;29258:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29244:54;;28286:1024;;;;27583:1727;29377:14;29373:203;;;29479:18;;29472:54;;-1:-1:-1;;;29472:54:0;;;;;2778:25:1;;;-1:-1:-1;;;;;29479:18:0;;;;29472:35;;2751:18:1;;29472:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16523:42;29541:23;;29373:203;29630:16;29665:11;;;;:17;29661:105;;29711:43;29724:17;29743:10;;29711:12;:43::i;:::-;29699:55;;;;:::i;:::-;;;29661:105;29847:1;29812:23;;;;;;;;:::i;:::-;-1:-1:-1;;;;;29812:37:0;;29808:399;;16610:5;29912:6;:18;;;:32;29904:62;;;;-1:-1:-1;;;29904:62:0;;12963:2:1;29904:62:0;;;12945:21:1;13002:2;12982:18;;;12975:30;-1:-1:-1;;;13021:18:1;;;13014:47;13078:18;;29904:62:0;12761:341:1;29904:62:0;29995:200;30025:17;30061:18;;;;;;30098:8;;30133:4;;30157:23;;;;;;:::i;29995:200::-;29983:212;;;;:::i;:::-;;;29808:399;-1:-1:-1;;;;;;;30223:24:0;;;30219:446;;30265:12;30283:15;;;;;;;;:::i;:::-;-1:-1:-1;;;;;30283:20:0;30329:28;30349:8;30329:17;:28;:::i;:::-;30283:93;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30264:112;;;30399:7;30391:35;;;;-1:-1:-1;;;30391:35:0;;;;;;;:::i;:::-;30249:189;30219:446;;;30503:150;30549:8;30576:15;;;;;;;;:::i;30503:150::-;30732:15;;;;;;;;:::i;:::-;-1:-1:-1;;;;;30682:180:0;30704:13;;;;:6;:13;:::i;:::-;-1:-1:-1;;;;;30682:180:0;;30762:8;30785:17;30817:8;30840:6;:11;;;30682:180;;;;;;;;;:::i;:::-;;;;;;;;30919:13;;30875:62;;30902:7;;-1:-1:-1;;;;;30919:13:0;;30875:26;:62::i;:::-;31219:6;:15;;;31205:11;:29;:63;;;;-1:-1:-1;31238:22:0;;;;;;;;:::i;:::-;:30;;31264:4;31238:30;31205:63;31201:562;;;31285:17;31305:29;31323:11;31305:15;;;;:29;:::i;:::-;31285:49;-1:-1:-1;31353:9:0;:14;31349:403;;31462:18;;31455:46;;-1:-1:-1;;;31455:46:0;;;;;2778:25:1;;;-1:-1:-1;;;;;31462:18:0;;;;31455:35;;2751:18:1;;31455:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31521:12:0;;-1:-1:-1;31539:13:0;;-1:-1:-1;;31539:13:0;;;:6;:13;:::i;:::-;-1:-1:-1;;;;;31539:18:0;31565:9;31539:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31520:59;;;31606:7;31598:35;;;;-1:-1:-1;;;31598:35:0;;;;;;;:::i;:::-;31369:280;31349:403;;;31674:62;31702:7;31711:13;;;;:6;:13;:::i;31674:62::-;31270:493;31201:562;-1:-1:-1;31782:11:0;;25140:6661;-1:-1:-1;;;;;;25140:6661:0:o;22134:2563::-;22394:4;22419:6;22429:1;22419:11;22411:38;;;;-1:-1:-1;;;22411:38:0;;19287:2:1;22411:38:0;;;19269:21:1;19326:2;19306:18;;;19299:30;-1:-1:-1;;;19345:18:1;;;19338:44;19399:18;;22411:38:0;19085:338:1;22411:38:0;22536:1;22511:13;;;;:10;:13;:::i;:::-;-1:-1:-1;;;;;22511:27:0;;;:58;;;-1:-1:-1;22567:1:0;22542:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;22542:27:0;;;22511:58;22507:547;;;22605:23;;:::i;:::-;22647:32;;:::i;:::-;22733:93;22768:10;22801:6;22733:12;:93::i;:::-;22858:17;;22877:9;;22850:37;;2778:25:1;;;22698:128:0;;-1:-1:-1;22698:128:0;;-1:-1:-1;22698:128:0;;-1:-1:-1;;;;;;22850:37:0;;-1:-1:-1;;;;;;;;;;;22850:37:0;22858:17;2751:18:1;22850:37:0;;;;;;;22910:17;;;;-1:-1:-1;;;;;22910:31:0;;22906:122;;22979:17;;;;;22998:9;;;;22971:37;;2778:25:1;;;-1:-1:-1;;;;;22971:37:0;;;;-1:-1:-1;;;;;;;;;;;22971:37:0;2751:18:1;22971:37:0;;;;;;;22906:122;22586:457;;22507:547;-1:-1:-1;;;;;23070:21:0;;16523:42;23070:21;23066:347;;23162:50;;-1:-1:-1;;;23162:50:0;;23186:10;23162:50;;;19640:34:1;23206:4:0;19690:18:1;;;19683:43;23216:6:0;;-1:-1:-1;;;;;23162:23:0;;;;;19575:18:1;;23162:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:60;;23136:144;;;;-1:-1:-1;;;23136:144:0;;19939:2:1;23136:144:0;;;19921:21:1;19978:2;19958:18;;;19951:30;-1:-1:-1;;;19997:18:1;;;19990:52;20059:18;;23136:144:0;19737:346:1;23136:144:0;23066:347;;;23363:6;23350:9;:19;;23342:59;;;;-1:-1:-1;;;23342:59:0;;;;;;;:::i;:::-;23425:16;23462:10;;23458:258;;23501:203;23531:6;23556:10;;23585:5;16523:42;-1:-1:-1;;;;;23609:21:0;:5;-1:-1:-1;;;;;23609:21:0;;:50;;23649:10;23609:50;;;23641:4;23609:50;23678:11;;-1:-1:-1;;;;;23678:11:0;23501;:203::i;:::-;23489:215;;;;:::i;:::-;;;23458:258;-1:-1:-1;;;;;23732:30:0;;;23728:397;;16610:5;23825:11;:25;23817:58;;;;-1:-1:-1;;;23817:58:0;;20290:2:1;23817:58:0;;;20272:21:1;20329:2;20309:18;;;20302:30;-1:-1:-1;;;20348:18:1;;;20341:50;20408:18;;23817:58:0;20088:344:1;23817:58:0;23904:209;23934:6;23959:11;23989:5;-1:-1:-1;;;;;24013:21:0;;16523:42;24013:21;:50;;24053:10;24013:50;;;24045:4;24013:50;24082:16;23904:11;:209::i;:::-;23892:221;;;;:::i;:::-;;;23728:397;-1:-1:-1;;;;;24174:21:0;;16523:42;24174:21;24170:418;;24240:162;24290:5;24314:10;24343:8;24370:17;24379:8;24370:6;:17;:::i;:::-;24240:31;:162::i;:::-;24170:418;;;24465:12;-1:-1:-1;;;;;24483:13:0;;24504:17;24513:8;24504:6;:17;:::i;:::-;24483:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24464:62;;;24549:7;24541:35;;;;-1:-1:-1;;;24541:35:0;;;;;;;:::i;:::-;24420:168;24170:418;24625:8;-1:-1:-1;;;;;24605:60:0;24613:10;-1:-1:-1;;;;;24605:60:0;;24635:5;24642:6;24650:8;24660:4;24605:60;;;;;;;;;:::i;:::-;;;;;;;;24685:4;24678:11;;;22134:2563;;;;;;;;;;:::o;7929:103::-;7167:13;:11;:13::i;:::-;7994:30:::1;8021:1;7994:18;:30::i;:::-;7929:103::o:0;8187:201::-;7167:13;:11;:13::i;:::-;-1:-1:-1;;;;;8276:22:0;::::1;8268:73;;;::::0;-1:-1:-1;;;8268:73:0;;20639:2:1;8268:73:0::1;::::0;::::1;20621:21:1::0;20678:2;20658:18;;;20651:30;20717:34;20697:18;;;20690:62;-1:-1:-1;;;20768:18:1;;;20761:36;20814:19;;8268:73:0::1;20437:402:1::0;8268:73:0::1;8352:28;8371:8;8352:18;:28::i;7446:132::-:0;7327:7;7354:6;-1:-1:-1;;;;;7354:6:0;6070:10;7510:23;7502:68;;;;-1:-1:-1;;;7502:68:0;;21046:2:1;7502:68:0;;;21028:21:1;;;21065:18;;;21058:30;21124:34;21104:18;;;21097:62;21176:18;;7502:68:0;20844:356:1;3961:316:0;4126:59;;;-1:-1:-1;;;;;21397:32:1;;;4126:59:0;;;21379:51:1;21446:18;;;;21439:34;;;4126:59:0;;;;;;;;;;21352:18:1;;;;4126:59:0;;;;;;;-1:-1:-1;;;;;4126:59:0;-1:-1:-1;;;4126:59:0;;;4115:71;;-1:-1:-1;;;;4115:10:0;;;;:71;;4126:59;4115:71;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4079:107;;;;4205:7;:57;;;;-1:-1:-1;4217:11:0;;:16;;:44;;;4248:4;4237:24;;;;;;;;;;;;:::i;:::-;4197:72;;;;-1:-1:-1;;;4197:72:0;;22215:2:1;4197:72:0;;;22197:21:1;22254:1;22234:18;;;22227:29;-1:-1:-1;;;22272:18:1;;;22265:32;22314:18;;4197:72:0;22013:325:1;4197:72:0;4068:209;;3961:316;;;:::o;42626:599::-;42773:8;;42811;;;;42726:7;;;;42956:1;42942:170;42964:1;42959;:6;42942:170;;43015:1;42991:5;42997;:1;43001;42997:5;:::i;:::-;42991:12;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;42991:26:0;;42987:114;;43049:5;43055;:1;43059;43055:5;:::i;:::-;43049:12;;;;;;;:::i;:::-;;;;;43038:23;;43080:5;;42987:114;42967:3;;;;:::i;:::-;;;;42942:170;;;-1:-1:-1;;;;;;43130:22:0;;43122:58;;;;-1:-1:-1;;;43122:58:0;;22686:2:1;43122:58:0;;;22668:21:1;22725:2;22705:18;;;22698:30;22764:25;22744:18;;;22737:53;22807:18;;43122:58:0;22484:347:1;43122:58:0;43199:8;43209:7;;-1:-1:-1;42626:599:0;-1:-1:-1;;42626:599:0:o;3295:367::-;3500:69;;;-1:-1:-1;;;;;23094:15:1;;;3500:69:0;;;23076:34:1;23146:15;;;23126:18;;;23119:43;23178:18;;;;23171:34;;;3500:69:0;;;;;;;;;;23011:18:1;;;;3500:69:0;;;;;;;-1:-1:-1;;;;;3500:69:0;-1:-1:-1;;;3500:69:0;;;3489:81;;-1:-1:-1;;;;3489:10:0;;;;:81;;3500:69;3489:81;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3440:130;;;;3589:7;:57;;;;-1:-1:-1;3601:11:0;;:16;;:44;;;3632:4;3621:24;;;;;;;;;;;;:::i;:::-;3581:73;;;;-1:-1:-1;;;3581:73:0;;23418:2:1;3581:73:0;;;23400:21:1;23457:1;23437:18;;;23430:29;-1:-1:-1;;;23475:18:1;;;23468:33;23518:18;;3581:73:0;23216:326:1;3581:73:0;3429:233;;3295:367;;;;:::o;4637:314::-;4801:58;;;-1:-1:-1;;;;;21397:32:1;;;4801:58:0;;;21379:51:1;21446:18;;;;21439:34;;;4801:58:0;;;;;;;;;;21352:18:1;;;;4801:58:0;;;;;;;-1:-1:-1;;;;;4801:58:0;-1:-1:-1;;;4801:58:0;;;4790:70;;-1:-1:-1;;;;4790:10:0;;;;:70;;4801:58;4790:70;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4754:106;;;;4879:7;:57;;;;-1:-1:-1;4891:11:0;;:16;;:44;;;4922:4;4911:24;;;;;;;;;;;;:::i;:::-;4871:72;;;;-1:-1:-1;;;4871:72:0;;23749:2:1;4871:72:0;;;23731:21:1;23788:1;23768:18;;;23761:29;-1:-1:-1;;;23806:18:1;;;23799:32;23848:18;;4871:72:0;23547:325:1;43878:1061:0;44041:7;44061:11;44075:28;44088:6;44096;44075:12;:28::i;:::-;44061:42;-1:-1:-1;44118:7:0;;44114:818;;-1:-1:-1;;;;;44146:21:0;;16523:42;44146:21;44142:713;;44240:4;-1:-1:-1;;;;;44224:21:0;;;44220:274;;44270:43;44298:5;44305:2;44309:3;44270:27;:43::i;:::-;44142:713;;44220:274;44421:53;44453:5;44460:4;44466:2;44470:3;44421:31;:53::i;44142:713::-;-1:-1:-1;;;;;44564:21:0;;44580:4;44564:21;44534:140;;;;-1:-1:-1;;;44534:140:0;;24079:2:1;44534:140:0;;;24061:21:1;24118:2;24098:18;;;24091:30;24157:34;24137:18;;;24130:62;-1:-1:-1;;;24208:18:1;;;24201:43;24261:19;;44534:140:0;23877:409:1;44534:140:0;44729:12;44747:2;-1:-1:-1;;;;;44747:7:0;44762:3;44747:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44728:42;;;44797:7;44789:50;;;;-1:-1:-1;;;44789:50:0;;24493:2:1;44789:50:0;;;24475:21:1;24532:2;24512:18;;;24505:30;24571:32;24551:18;;;24544:60;24621:18;;44789:50:0;24291:354:1;44789:50:0;44515:340;44142:713;44876:3;-1:-1:-1;44869:10:0;;44114:818;44919:1;44912:8;;;43878:1061;;;;;;;;:::o;41359:591::-;41476:7;;;;;41562:8;:27;;;;;;;;:::i;:::-;;41558:348;;41659:4;41630:93;;;;;;;;;;;;:::i;:::-;41606:117;;-1:-1:-1;41606:117:0;;-1:-1:-1;41558:348:0;;-1:-1:-1;41558:348:0;;41813:4;41784:110;;;;;;;;;;;;:::i;:::-;41756:138;;-1:-1:-1;41756:138:0;;-1:-1:-1;;;;41558:348:0;41924:8;;-1:-1:-1;41934:7:0;-1:-1:-1;41359:591:0;;;;;;:::o;42137:206::-;42224:6;42246:14;42277:4;42266:44;;;;;;;;;;;;:::i;:::-;-1:-1:-1;42243:67:0;42137:206;-1:-1:-1;;;;42137:206:0:o;8548:191::-;8622:16;8641:6;;-1:-1:-1;;;;;8658:17:0;;;-1:-1:-1;;;;;;8658:17:0;;;;;;8691:40;;8641:6;;;;;;;8691:40;;8622:16;8691:40;8611:128;8548:191;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:131:1:-;-1:-1:-1;;;;;89:31:1;;79:42;;69:70;;135:1;132;125:12;150:247;209:6;262:2;250:9;241:7;237:23;233:32;230:52;;;278:1;275;268:12;230:52;317:9;304:23;336:31;361:5;336:31;:::i;:::-;386:5;150:247;-1:-1:-1;;;150:247:1:o;402:159::-;496:6;529:2;517:15;;514:24;-1:-1:-1;511:44:1;;;551:1;548;541:12;566:303;659:6;667;720:2;708:9;699:7;695:23;691:32;688:52;;;736:1;733;726:12;688:52;759:53;804:7;793:9;759:53;:::i;:::-;749:63;859:2;844:18;;;;831:32;;-1:-1:-1;;;566:303:1:o;983:961::-;1276:25;;;1263:3;1248:19;;1320:2;1342:18;;;1402:6;1221:4;1436:193;1450:4;1447:1;1444:11;1436:193;;;1513:13;;-1:-1:-1;;;;;1509:39:1;1497:52;;1569:12;;;;1604:15;;;;1545:1;1463:9;1436:193;;;1440:3;;;1666:2;1655:9;1651:18;1717:6;1743:1;1753:185;1769:4;1764:3;1761:13;1753:185;;;1834:15;;1820:30;;1872:14;;;;1911:17;;;;1793:1;1784:11;1753:185;;;1757:3;;;;983:961;;;;;;:::o;2379:248::-;2447:6;2455;2508:2;2496:9;2487:7;2483:23;2479:32;2476:52;;;2524:1;2521;2514:12;2476:52;-1:-1:-1;;2547:23:1;;;2617:2;2602:18;;;2589:32;;-1:-1:-1;2379:248:1:o;2814:202::-;2907:6;2960:4;2948:9;2939:7;2935:23;2931:34;2928:54;;;2978:1;2975;2968:12;2928:54;-1:-1:-1;3001:9:1;2814:202;-1:-1:-1;2814:202:1:o;3021:258::-;3093:1;3103:113;3117:6;3114:1;3111:13;3103:113;;;3193:11;;;3187:18;3174:11;;;3167:39;3139:2;3132:10;3103:113;;;3234:6;3231:1;3228:13;3225:48;;;3269:1;3260:6;3255:3;3251:16;3244:27;3225:48;;3021:258;;;:::o;3284:::-;3326:3;3364:5;3358:12;3391:6;3386:3;3379:19;3407:63;3463:6;3456:4;3451:3;3447:14;3440:4;3433:5;3429:16;3407:63;:::i;:::-;3524:2;3503:15;-1:-1:-1;;3499:29:1;3490:39;;;;3531:4;3486:50;;3284:258;-1:-1:-1;;3284:258:1:o;3547:220::-;3696:2;3685:9;3678:21;3659:4;3716:45;3757:2;3746:9;3742:18;3734:6;3716:45;:::i;3772:396::-;3867:6;3920:2;3908:9;3899:7;3895:23;3891:32;3888:52;;;3936:1;3933;3926:12;3888:52;3976:9;3963:23;4009:18;4001:6;3998:30;3995:50;;;4041:1;4038;4031:12;3995:50;4064:22;;4120:3;4102:16;;;4098:26;4095:46;;;4137:1;4134;4127:12;4173:861;4311:6;4319;4327;4335;4343;4351;4359;4412:3;4400:9;4391:7;4387:23;4383:33;4380:53;;;4429:1;4426;4419:12;4380:53;4465:9;4452:23;4442:33;;4522:2;4511:9;4507:18;4494:32;4484:42;;4545:62;4599:7;4594:2;4583:9;4579:18;4545:62;:::i;:::-;4535:72;;4657:3;4646:9;4642:19;4629:33;4671:31;4696:5;4671:31;:::i;:::-;4721:5;-1:-1:-1;4778:3:1;4763:19;;4750:33;4792;4750;4792;:::i;:::-;4844:7;-1:-1:-1;4903:3:1;4888:19;;4875:33;4917;4875;4917;:::i;:::-;4969:7;4959:17;;;5023:3;5012:9;5008:19;4995:33;4985:43;;4173:861;;;;;;;;;;:::o;6249:184::-;6319:6;6372:2;6360:9;6351:7;6347:23;6343:32;6340:52;;;6388:1;6385;6378:12;6340:52;-1:-1:-1;6411:16:1;;6249:184;-1:-1:-1;6249:184:1:o;6438:127::-;6499:10;6494:3;6490:20;6487:1;6480:31;6530:4;6527:1;6520:15;6554:4;6551:1;6544:15;6917:273;6985:6;7038:2;7026:9;7017:7;7013:23;7009:32;7006:52;;;7054:1;7051;7044:12;7006:52;7086:9;7080:16;7136:4;7129:5;7125:16;7118:5;7115:27;7105:55;;7156:1;7153;7146:12;7195:127;7256:10;7251:3;7247:20;7244:1;7237:31;7287:4;7284:1;7277:15;7311:4;7308:1;7301:15;7327:422;7416:1;7459:5;7416:1;7473:270;7494:7;7484:8;7481:21;7473:270;;;7553:4;7549:1;7545:6;7541:17;7535:4;7532:27;7529:53;;;7562:18;;:::i;:::-;7612:7;7602:8;7598:22;7595:55;;;7632:16;;;;7595:55;7711:22;;;;7671:15;;;;7473:270;;;7477:3;7327:422;;;;;:::o;7754:806::-;7803:5;7833:8;7823:80;;-1:-1:-1;7874:1:1;7888:5;;7823:80;7922:4;7912:76;;-1:-1:-1;7959:1:1;7973:5;;7912:76;8004:4;8022:1;8017:59;;;;8090:1;8085:130;;;;7997:218;;8017:59;8047:1;8038:10;;8061:5;;;8085:130;8122:3;8112:8;8109:17;8106:43;;;8129:18;;:::i;:::-;-1:-1:-1;;8185:1:1;8171:16;;8200:5;;7997:218;;8299:2;8289:8;8286:16;8280:3;8274:4;8271:13;8267:36;8261:2;8251:8;8248:16;8243:2;8237:4;8234:12;8230:35;8227:77;8224:159;;;-1:-1:-1;8336:19:1;;;8368:5;;8224:159;8415:34;8440:8;8434:4;8415:34;:::i;:::-;8485:6;8481:1;8477:6;8473:19;8464:7;8461:32;8458:58;;;8496:18;;:::i;:::-;8534:20;;7754:806;-1:-1:-1;;;7754:806:1:o;8565:131::-;8625:5;8654:36;8681:8;8675:4;8654:36;:::i;8701:179::-;8779:13;;8832:22;8821:34;;8811:45;;8801:73;;8870:1;8867;8860:12;8801:73;8701:179;;;:::o;8885:473::-;8988:6;8996;9004;9012;9020;9073:3;9061:9;9052:7;9048:23;9044:33;9041:53;;;9090:1;9087;9080:12;9041:53;9113:39;9142:9;9113:39;:::i;:::-;9103:49;;9192:2;9181:9;9177:18;9171:25;9161:35;;9236:2;9225:9;9221:18;9215:25;9205:35;;9280:2;9269:9;9265:18;9259:25;9249:35;;9303:49;9347:3;9336:9;9332:19;9303:49;:::i;:::-;9293:59;;8885:473;;;;;;;;:::o;9363:168::-;9403:7;9469:1;9465;9461:6;9457:14;9454:1;9451:21;9446:1;9439:9;9432:17;9428:45;9425:71;;;9476:18;;:::i;:::-;-1:-1:-1;9516:9:1;;9363:168::o;9536:217::-;9576:1;9602;9592:132;;9646:10;9641:3;9637:20;9634:1;9627:31;9681:4;9678:1;9671:15;9709:4;9706:1;9699:15;9592:132;-1:-1:-1;9738:9:1;;9536:217::o;10291:351::-;10493:2;10475:21;;;10532:2;10512:18;;;10505:30;10571:29;10566:2;10551:18;;10544:57;10633:2;10618:18;;10291:351::o;10647:449::-;10749:5;10772:1;10782:308;10796:4;10793:1;10790:11;10782:308;;;10871:6;10858:20;10891:33;10916:7;10891:33;:::i;:::-;-1:-1:-1;;;;;10949:33:1;10937:46;;11006:4;11030:12;;;;11065:15;;;;;10979:1;10809:9;10782:308;;11101:1522;11567:3;11552:19;;11556:9;11648:6;11525:4;;11703:308;11719:4;11714:3;11711:13;11703:308;;;11796:6;11783:20;11816:31;11841:5;11816:31;:::i;:::-;-1:-1:-1;;;;;11872:31:1;11860:44;;11927:4;11951:12;;;;11986:15;;;;;11900:1;11734:11;11703:308;;;11707:3;12048;12037:9;12033:19;12020:32;;12100:6;12084:22;;12126:1;12136:266;12152:4;12147:3;12144:13;12136:266;;;12213:4;12260:2;12250:8;12243:5;12230:33;12286:14;;;12313:13;;;12286:14;12375:17;;;;;12176:1;12167:11;12136:266;;;12140:3;;;;12439:6;12433:3;12422:9;12418:19;12411:35;12483:6;12477:3;12466:9;12462:19;12455:35;12499:62;12556:3;12545:9;12541:19;12533:6;12499:62;:::i;:::-;-1:-1:-1;;;;;940:31:1;;12612:3;12597:19;;928:44;12570:47;874:104;12628:128;12668:3;12699:1;12695:6;12692:1;12689:13;12686:39;;;12705:18;;:::i;:::-;-1:-1:-1;12741:9:1;;12628:128::o;13107:125::-;13147:4;13175:1;13172;13169:8;13166:34;;;13180:18;;:::i;:::-;-1:-1:-1;13217:9:1;;13107:125::o;13237:339::-;13439:2;13421:21;;;13478:2;13458:18;;;13451:30;-1:-1:-1;;;13512:2:1;13497:18;;13490:45;13567:2;13552:18;;13237:339::o;13581:417::-;-1:-1:-1;;;;;13830:32:1;;;;13812:51;;13894:2;13879:18;;13872:34;;;;13937:2;13922:18;;13915:34;13980:2;13965:18;;13958:34;13799:3;13784:19;;13581:417::o;14003:118::-;14089:5;14082:13;14075:21;14068:5;14065:32;14055:60;;14111:1;14108;14101:12;14126:241;14182:6;14235:2;14223:9;14214:7;14210:23;14206:32;14203:52;;;14251:1;14248;14241:12;14203:52;14290:9;14277:23;14309:28;14331:5;14309:28;:::i;14372:380::-;14451:1;14447:12;;;;14494;;;14515:61;;14569:4;14561:6;14557:17;14547:27;;14515:61;14622:2;14614:6;14611:14;14591:18;14588:38;14585:161;;14668:10;14663:3;14659:20;14656:1;14649:31;14703:4;14700:1;14693:15;14731:4;14728:1;14721:15;15112:521;15189:4;15195:6;15255:11;15242:25;15349:2;15345:7;15334:8;15318:14;15314:29;15310:43;15290:18;15286:68;15276:96;;15368:1;15365;15358:12;15276:96;15395:33;;15447:20;;;-1:-1:-1;15490:18:1;15479:30;;15476:50;;;15522:1;15519;15512:12;15476:50;15555:4;15543:17;;-1:-1:-1;15586:14:1;15582:27;;;15572:38;;15569:58;;;15623:1;15620;15613:12;15638:268;15709:6;15762:2;15750:9;15741:7;15737:23;15733:32;15730:52;;;15778:1;15775;15768:12;15730:52;15817:9;15804:23;15856:1;15849:5;15846:12;15836:40;;15872:1;15869;15862:12;15911:127;15972:10;15967:3;15963:20;15960:1;15953:31;16003:4;16000:1;15993:15;16027:4;16024:1;16017:15;16843:119;16928:8;16921:5;16917:20;16910:5;16907:31;16897:59;;16952:1;16949;16942:12;16967:833;17084:6;17092;17100;17108;17116;17169:3;17157:9;17148:7;17144:23;17140:33;17137:53;;;17186:1;17183;17176:12;17137:53;17225:9;17212:23;17244:31;17269:5;17244:31;:::i;:::-;17294:5;-1:-1:-1;17351:2:1;17336:18;;17323:32;17364;17323;17364;:::i;:::-;17415:7;-1:-1:-1;17474:2:1;17459:18;;17446:32;17487:33;17446:32;17487:33;:::i;:::-;17539:7;-1:-1:-1;17598:2:1;17583:18;;17570:32;17611;17570;17611;:::i;:::-;17662:7;-1:-1:-1;17721:3:1;17706:19;;17693:33;17735;17693;17735;:::i;:::-;17787:7;17777:17;;;16967:833;;;;;;;;:::o;18427:653::-;18624:2;18613:9;18606:21;18587:4;18662:6;18656:13;18705:4;18700:2;18689:9;18685:18;18678:32;18733:52;18780:3;18769:9;18765:19;18751:12;18733:52;:::i;:::-;18719:66;;18866:1;18862;18857:3;18853:11;18849:19;18843:2;18835:6;18831:15;18825:22;18821:48;18816:2;18805:9;18801:18;18794:76;18924:2;18916:6;18912:15;18906:22;18901:2;18890:9;18886:18;18879:50;18984:2;18976:6;18972:15;18966:22;18960:3;18949:9;18945:19;18938:51;19045:3;19037:6;19033:16;19027:23;19020:4;19009:9;19005:20;18998:53;19068:6;19060:14;;;18427:653;;;;:::o;21484:274::-;21613:3;21651:6;21645:13;21667:53;21713:6;21708:3;21701:4;21693:6;21689:17;21667:53;:::i;:::-;21736:16;;;;;21484:274;-1:-1:-1;;21484:274:1:o;21763:245::-;21830:6;21883:2;21871:9;21862:7;21858:23;21854:32;21851:52;;;21899:1;21896;21889:12;21851:52;21931:9;21925:16;21950:28;21972:5;21950:28;:::i;22343:136::-;22382:3;22410:5;22400:39;;22419:18;;:::i;:::-;-1:-1:-1;;;22455:18:1;;22343:136::o;24650:533::-;24753:6;24761;24769;24822:2;24810:9;24801:7;24797:23;24793:32;24790:52;;;24838:1;24835;24828:12;24790:52;24870:9;24864:16;24889:31;24914:5;24889:31;:::i;:::-;24989:2;24974:18;;24968:25;24939:5;;-1:-1:-1;25002:32:1;24968:25;25002:32;:::i;:::-;25105:2;25090:18;;25084:25;25053:7;;-1:-1:-1;25118:33:1;25084:25;25118:33;:::i;:::-;25170:7;25160:17;;;24650:533;;;;;:::o;25188:809::-;25316:6;25324;25332;25340;25348;25401:3;25389:9;25380:7;25376:23;25372:33;25369:53;;;25418:1;25415;25408:12;25369:53;25450:9;25444:16;25469:31;25494:5;25469:31;:::i;:::-;25569:2;25554:18;;25548:25;25519:5;;-1:-1:-1;25582:32:1;25548:25;25582:32;:::i;:::-;25685:2;25670:18;;25664:25;25633:7;;-1:-1:-1;25698:33:1;25664:25;25698:33;:::i;:::-;25802:2;25787:18;;25781:25;25750:7;;-1:-1:-1;25815:32:1;25781:25;25815:32;:::i;:::-;25918:3;25903:19;;25897:26;25866:7;;-1:-1:-1;25932:33:1;25897:26;25932:33;:::i

Swarm Source

ipfs://fdfd1e319e66f69482d014c5ecc58850c9070303984da4fea86f3fb9f31af784

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.