POL Price: $0.703998 (+1.06%)
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Pay With Uniswap585397392024-06-24 7:00:20165 days ago1719212420IN
0x8866DAFa...CB2dA6100
0 POL0.0103610844.06984856
Pay With Uniswap585397312024-06-24 6:59:48165 days ago1719212388IN
0x8866DAFa...CB2dA6100
0 POL0.0075879241.56037182
Pay With Token585397152024-06-24 6:59:06165 days ago1719212346IN
0x8866DAFa...CB2dA6100
0 POL0.0023817341.5696133
Pay With Token585396972024-06-24 6:58:28165 days ago1719212308IN
0x8866DAFa...CB2dA6100
0 POL0.0032893840.54112384
Pay With Uniswap585396772024-06-24 6:57:44165 days ago1719212264IN
0x8866DAFa...CB2dA6100
1.81294992 POL0.007447142.76627348
Pay With Token585396462024-06-24 6:56:36165 days ago1719212196IN
0x8866DAFa...CB2dA6100
1.93872834 POL0.0036608645.59491468
Pay With Token585396342024-06-24 6:55:48165 days ago1719212148IN
0x8866DAFa...CB2dA6100
1.93837732 POL0.002947541.81327564
Pay With Token585396252024-06-24 6:55:22165 days ago1719212122IN
0x8866DAFa...CB2dA6100
1.81125045 POL0.0024089341.68139641
Pay With Token584820952024-06-22 20:00:37167 days ago1719086437IN
0x8866DAFa...CB2dA6100
1.75300201 POL0.0017338230.00000003
Pay With Token584820722024-06-22 19:59:49167 days ago1719086389IN
0x8866DAFa...CB2dA6100
1.75315568 POL0.0017338230.00000002
Pay With Token584240342024-06-21 9:17:37168 days ago1718961457IN
0x8866DAFa...CB2dA6100
1.76454973 POL0.0038656166.88608796
Pay With Token584240342024-06-21 9:17:37168 days ago1718961457IN
0x8866DAFa...CB2dA6100
1.75229989 POL0.0038656166.88608796
Pay With Token584237242024-06-21 9:06:37168 days ago1718960797IN
0x8866DAFa...CB2dA6100
1.75492888 POL0.0051952489.89245092
Pay With Token584236592024-06-21 9:04:19168 days ago1718960659IN
0x8866DAFa...CB2dA6100
1.77465678 POL0.00649134112.31866707
Pay With Token584219142024-06-21 8:02:22168 days ago1718956942IN
0x8866DAFa...CB2dA6100
1.74153332 POL0.0017623930.49434208
Pay With Token584015802024-06-20 19:43:43169 days ago1718912623IN
0x8866DAFa...CB2dA6100
1.74327286 POL0.0017338230.00000002
Pay With Token584015522024-06-20 19:42:45169 days ago1718912565IN
0x8866DAFa...CB2dA6100
1.74270379 POL0.0017338230.00000003
Pay With Token584009992024-06-20 19:21:33169 days ago1718911293IN
0x8866DAFa...CB2dA6100
0.17272637 POL0.0017338230.00000002
Pay With Token584009372024-06-20 19:19:21169 days ago1718911161IN
0x8866DAFa...CB2dA6100
0.17264224 POL0.0014398530.00000002
Pay With Token583964762024-06-20 16:40:47169 days ago1718901647IN
0x8866DAFa...CB2dA6100
0.0174926 POL0.001766130.56501752
Pay With Token583948102024-06-20 15:41:19169 days ago1718898079IN
0x8866DAFa...CB2dA6100
8.78108155 POL0.0030705836
Pay With Uniswap583044972024-06-18 9:01:34171 days ago1718701294IN
0x8866DAFa...CB2dA6100
0.0179964 POL0.0060525433.44483135
Pay With Token582620872024-06-17 7:45:56172 days ago1718610356IN
0x8866DAFa...CB2dA6100
0.01667134 POL0.001754830.36944846
Pay With Token582620752024-06-17 7:45:30172 days ago1718610330IN
0x8866DAFa...CB2dA6100
0.01667134 POL0.0017559130.388659
Pay With Token582580232024-06-17 5:18:47173 days ago1718601527IN
0x8866DAFa...CB2dA6100
0.01631961 POL0.0017334630.00000004
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
585396772024-06-24 6:57:44165 days ago1719212264
0x8866DAFa...CB2dA6100
0.00181113 POL
585396772024-06-24 6:57:44165 days ago1719212264
0x8866DAFa...CB2dA6100
0.00181113 POL
585396772024-06-24 6:57:44165 days ago1719212264
0x8866DAFa...CB2dA6100
1.81294992 POL
585396462024-06-24 6:56:36165 days ago1719212196
0x8866DAFa...CB2dA6100
1.93737328 POL
585396252024-06-24 6:55:22165 days ago1719212122
0x8866DAFa...CB2dA6100
1.81120741 POL
584820952024-06-22 20:00:37167 days ago1719086437
0x8866DAFa...CB2dA6100
1.75283227 POL
584820722024-06-22 19:59:49167 days ago1719086389
0x8866DAFa...CB2dA6100
1.75311532 POL
584240342024-06-21 9:17:37168 days ago1718961457
0x8866DAFa...CB2dA6100
1.74373997 POL
584240342024-06-21 9:17:37168 days ago1718961457
0x8866DAFa...CB2dA6100
1.74373997 POL
584237242024-06-21 9:06:37168 days ago1718960797
0x8866DAFa...CB2dA6100
1.75392994 POL
584236592024-06-21 9:04:19168 days ago1718960659
0x8866DAFa...CB2dA6100
1.75802084 POL
584219142024-06-21 8:02:22168 days ago1718956942
0x8866DAFa...CB2dA6100
1.7401521 POL
584015802024-06-20 19:43:43169 days ago1718912623
0x8866DAFa...CB2dA6100
1.72554127 POL
584015522024-06-20 19:42:45169 days ago1718912565
0x8866DAFa...CB2dA6100
1.72589784 POL
584009992024-06-20 19:21:33169 days ago1718911293
0x8866DAFa...CB2dA6100
0.17263495 POL
583964762024-06-20 16:40:47169 days ago1718901647
0x8866DAFa...CB2dA6100
0.01744918 POL
583948102024-06-20 15:41:19169 days ago1718898079
0x8866DAFa...CB2dA6100
8.69565217 POL
583105502024-06-18 12:36:20171 days ago1718714180
0x8866DAFa...CB2dA6100
0.00001172 POL
583105502024-06-18 12:36:20171 days ago1718714180
0x8866DAFa...CB2dA6100
0.00001172 POL
583105502024-06-18 12:36:20171 days ago1718714180
0x8866DAFa...CB2dA6100
0.01832659 POL
583105502024-06-18 12:36:20171 days ago1718714180
0x8866DAFa...CB2dA6100
0.01832659 POL
583077552024-06-18 10:57:04171 days ago1718708224
0x8866DAFa...CB2dA6100
0.00003585 POL
583077552024-06-18 10:57:04171 days ago1718708224
0x8866DAFa...CB2dA6100
0.00003585 POL
583077552024-06-18 10:57:04171 days ago1718708224
0x8866DAFa...CB2dA6100
0.03589284 POL
583077552024-06-18 10:57:04171 days ago1718708224
0x8866DAFa...CB2dA6100
0.03589284 POL
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 polygonscan.com on 2023-09-09
*/

//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"}]

60806040523480156200001157600080fd5b5060405162002fde38038062002fde8339810160408190526200003491620001e5565b6200003f33620000bc565b6002859055600180546001600160a01b0319166001600160a01b0388161790558351620000749060069060208701906200010c565b50600380546001600160a01b039485166001600160a01b0319918216179091556004805493851693821693909317909255600580549190931691161790555062000354915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280546200011a9062000318565b90600052602060002090601f0160209004810192826200013e576000855562000189565b82601f106200015957805160ff191683800117855562000189565b8280016001018555821562000189579182015b82811115620001895782518255916020019190600101906200016c565b50620001979291506200019b565b5090565b5b808211156200019757600081556001016200019c565b80516001600160a01b0381168114620001ca57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c08789031215620001ff57600080fd5b6200020a87620001b2565b60208881015160408a01519298509650906001600160401b03808211156200023157600080fd5b818a0191508a601f8301126200024657600080fd5b8151818111156200025b576200025b620001cf565b604051601f8201601f19908116603f01168101908382118183101715620002865762000286620001cf565b816040528281528d868487010111156200029f57600080fd5b600093505b82841015620002c35784840186015181850187015292850192620002a4565b82841115620002d55760008684830101525b809950505050505050620002ec60608801620001b2565b9250620002fc60808801620001b2565b91506200030c60a08801620001b2565b90509295509295509295565b600181811c908216806200032d57607f821691505b6020821081036200034e57634e487b7160e01b600052602260045260246000fd5b50919050565b612c7a80620003646000396000f3fe6080604052600436106101025760003560e01c806360dc2340116100955780638da5cb5b116100645780638da5cb5b146102b6578063bf5a5940146102d4578063cda90b88146102ea578063d55be8c61461030a578063f2fde38b1461032057600080fd5b806360dc23401461023e5780636404f8fe1461025e578063715018a614610281578063735de9f71461029657600080fd5b806334e73122116100d157806334e73122146101c8578063534ce2a5146101f657806354fd4d50146102095780636038ce651461022b57600080fd5b806301681a621461010e5780630d742ff71461013057806317fcb39b1461016857806331f7d964146101a057600080fd5b3661010957005b600080fd5b34801561011a57600080fd5b5061012e6101293660046123a9565b610340565b005b34801561013c57600080fd5b5061015061014b3660046123de565b610496565b60405161015f93929190612409565b60405180910390f35b34801561017457600080fd5b50600554610188906001600160a01b031681565b6040516001600160a01b03909116815260200161015f565b3480156101ac57600080fd5b5061018873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156101d457600080fd5b506101e86101e3366004612473565b610808565b60405190815260200161015f565b6101e8610204366004612495565b61082a565b34801561021557600080fd5b5061021e610e22565b60405161015f919061250a565b6101e861023936600461251d565b610eb0565b34801561024a57600080fd5b50600154610188906001600160a01b031681565b61027161026c366004612559565b611809565b604051901515815260200161015f565b34801561028d57600080fd5b5061012e611c46565b3480156102a257600080fd5b50600354610188906001600160a01b031681565b3480156102c257600080fd5b506000546001600160a01b0316610188565b3480156102e057600080fd5b506101e860025481565b3480156102f657600080fd5b50600454610188906001600160a01b031681565b34801561031657600080fd5b506101e861138881565b34801561032c57600080fd5b5061012e61033b3660046123a9565b611c5a565b610348611cd0565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03821601610419576001546040516000916001600160a01b03169047908381818185875af1925050503d80600081146103ba576040519150601f19603f3d011682016040523d82523d6000602084013e6103bf565b606091505b50509050806104155760405162461bcd60e51b815260206004820152601860248201527f7472616e73666572206661696c656420696e207377656570000000000000000060448201526064015b60405180910390fd5b5050565b6001546040516370a0823160e01b81523060048201526104939183916001600160a01b03918216918316906370a0823190602401602060405180830381865afa15801561046a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048e91906125d4565b611d2a565b50565b60006104a0612376565b6104a8612376565b60006104b760208701876123a9565b6001600160a01b03161415806104e6575060006104da60408701602088016123a9565b6001600160a01b031614155b6105275760405162461bcd60e51b8152602060048201526012602482015271696e76616c6964207072696365666565647360701b604482015260640161040c565b600080808061053960208a018a6123a9565b6001600160a01b031603610562576001925061055b6040890160208a016123a9565b91506105a4565b61056f60208901896123a9565b9150600061058360408a0160208b016123a9565b6001600160a01b0316146105a4576105a16040890160208a016123a9565b90505b6000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106089190612603565b6106169060ff16600a612720565b90506000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610658573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067c919061274b565b5050509150508086600060028110610696576106966125ed565b602002015284156106bd57806106ac838b61279b565b6106b691906127ba565b97506106d5565b816106c8828b61279b565b6106d291906127ba565b97505b6001600160a01b038316156107de57826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107469190612603565b6107549060ff16600a612720565b9150826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610794573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b8919061274b565b5050506020880181905291508190506107d1838a61279b565b6107db91906127ba565b97505b5050604080518082019091526001600160a01b039283168152911660208201529250509250925092565b6000612710610817838561279b565b61082191906127ba565b90505b92915050565b6004546000906001600160a01b03166108855760405162461bcd60e51b815260206004820152601860248201527f637572766520726f75746572206e6f742070726573656e740000000000000000604482015260640161040c565b6000806108bd8460a0016009806020026040519081016040528092919082600960200280828437600092019190915250611e2a915050565b90925090506000806108d76103e087016103c088016123a9565b6001600160a01b0316141580610908575060006108fc61040087016103e088016123a9565b6001600160a01b031614155b156109b757610915612376565b61091d612376565b61092f876103c0018860600135610496565b815181516040519081529396509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b0316156109b057602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b50506109be565b5060608401355b3415610a695784604001353410156109e85760405162461bcd60e51b815260040161040c906127dc565b600560009054906101000a90046001600160a01b03166001600160a01b031663d0e30db086604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a3c57600080fd5b505af1158015610a50573d6000803e3d6000fd5b50506005546001600160a01b03169450610a7992505050565b610a798233308860400135611f0c565b600454610a959083906001600160a01b03166040880135612016565b6004805460408051630651cb3560e01b81526000936001600160a01b0390931692630651cb3592610adf9260a08c01926101c08d01928d01359189916103408f0191309101612849565b6020604051808303816000875af1158015610afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2291906125d4565b90506000608087013515610b4957610b3c83600254610808565b610b4690826128eb565b90505b6000610b5d61042089016104008a016123a9565b6001600160a01b031614610be55761138887610420013510610bb55760405162461bcd60e51b81526020600482015260116024820152700caf0e8e4c28ccaca40e8dede40d0d2ced607b1b604482015260640161040c565b610bd883610420890180359088903090610bd3906104008e016123a9565b61210f565b610be290826128eb565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03861601610c97576000610c1c6040890160208a016123a9565b6001600160a01b0316610c2f8386612903565b604051600081818185875af1925050503d8060008114610c6b576040519150601f19603f3d011682016040523d82523d6000602084013e610c70565b606091505b5050905080610c915760405162461bcd60e51b815260040161040c9061291a565b50610cb5565b610cb585610cab60408a0160208b016123a9565b61048e8487612903565b610cc560408801602089016123a9565b6001600160a01b0316610cdb60208901896123a9565b6001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac168786858c60800135604051610d1d9493929190612943565b60405180910390a36000610d318484612903565b9050600081118015610d505750610d5061046089016104408a01612977565b15610e165773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601610dff576000610d8960208a018a6123a9565b6001600160a01b03168260405160006040518083038185875af1925050503d8060008114610dd3576040519150601f19603f3d011682016040523d82523d6000602084013e610dd8565b606091505b5050905080610df95760405162461bcd60e51b815260040161040c9061291a565b50610e16565b610e1686610e1060208b018b6123a9565b83611d2a565b50909695505050505050565b60068054610e2f90612994565b80601f0160208091040260200160405190810160405280929190818152602001828054610e5b90612994565b8015610ea85780601f10610e7d57610100808354040283529160200191610ea8565b820191906000526020600020905b815481529060010190602001808311610e8b57829003601f168201915b505050505081565b6003546000906001600160a01b0316610f0b5760405162461bcd60e51b815260206004820152601a60248201527f756e697377617020726f75746572206e6f742070726573656e74000000000000604482015260640161040c565b600080610f6a610f1e60a08601866129c8565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610f659250505061018087016101608801612a0f565b61229d565b909250905060008080610f8360e0880160c089016123a9565b6001600160a01b0316141580610fb357506000610fa7610100880160e089016123a9565b6001600160a01b031614155b1561106157610fc0612376565b610fc8612376565b610fd98860c0018960600135610496565b815181516040519081529396509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b03161561105a57602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b5050611068565b5060608501355b34156111135785604001353410156110925760405162461bcd60e51b815260040161040c906127dc565b600560009054906101000a90046001600160a01b03166001600160a01b031663d0e30db087604001356040518263ffffffff1660e01b81526004016000604051808303818588803b1580156110e657600080fd5b505af11580156110fa573d6000803e3d6000fd5b50506005546001600160a01b0316955061112392505050565b6111238333308960400135611f0c565b60035461113f9084906001600160a01b03166040890135612016565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0386160161117857506005546001600160a01b0316935060015b600061118c61018089016101608a01612a0f565b600181111561119d5761119d612a30565b036113165760006111ee6111b460a08a018a6129c8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061230692505050565b60408051610100810182526001600160a01b038089168252898116602083015262ffffff84168284015230606083015242608083015260a082018790528b83013560c0830152600060e08301526003549251631b67c43360e31b8152939450909291169063db3e2198906112ca90849060040181516001600160a01b03908116825260208084015182169083015260408084015162ffffff16908301526060808401518216908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b6020604051808303816000875af11580156112e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130d91906125d4565b9450505061143b565b6000808061132760a08b018b6129c8565b8101906113349190612a57565b506040805160a0810182526bffffffffffffffffffffffff1960608f811b821660c08401526001600160e81b031960e888811b821660d486015287831b841660d786015286901b1660eb8401528e811b90911660ee830152825180830360e2018152610102830184528252306020830152428284015281018b90528f82013560808201526003549151631e51809360e31b81529498509296509094509092506001600160a01b03169063f28c0498906113f1908490600401612ac8565b6020604051808303816000875af1158015611410573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143491906125d4565b9650505050505b80156114b757600554604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561148757600080fd5b505af115801561149b573d6000803e3d6000fd5b5050505073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee94505b60006080880135156114dc576114cf83600254610808565b6114d990826128eb565b90505b60006114f06101208a016101008b016123a9565b6001600160a01b03161461157357611388886101200135106115485760405162461bcd60e51b81526020600482015260116024820152700caf0e8e4c28ccaca40e8dede40d0d2ced607b1b604482015260640161040c565b611566836101208a0180359089903090610bd3906101008f016123a9565b61157090826128eb565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038716016116255760006115aa60408a0160208b016123a9565b6001600160a01b03166115bd8386612903565b604051600081818185875af1925050503d80600081146115f9576040519150601f19603f3d011682016040523d82523d6000602084013e6115fe565b606091505b505090508061161f5760405162461bcd60e51b815260040161040c9061291a565b50611639565b61163986610cab60408b0160208c016123a9565b6116496040890160208a016123a9565b6001600160a01b031661165f60208a018a6123a9565b6001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac168886858d608001356040516116a19493929190612943565b60405180910390a36003546116c29086906001600160a01b03166000612016565b8760400135841080156116e857506116e261016089016101408a01612977565b15156001145b156117fd5760006116fd8560408b0135612903565b905034156117ea57600554604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561174b57600080fd5b505af115801561175f573d6000803e3d6000fd5b506000925061177491505060208b018b6123a9565b6001600160a01b03168260405160006040518083038185875af1925050503d80600081146117be576040519150601f19603f3d011682016040523d82523d6000602084013e6117c3565b606091505b50509050806117e45760405162461bcd60e51b815260040161040c9061291a565b506117fb565b6117fb86610e1060208c018c6123a9565b505b50919695505050505050565b60008660000361184c5760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b604482015260640161040c565b600061185b60208801886123a9565b6001600160a01b031614158061188a5750600061187e60408801602089016123a9565b6001600160a01b031614155b1561192d57611897612376565b61189f612376565b6118a9888a610496565b81518151604051908152939c509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b03161561192a57602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b50505b6001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611a0d57604051636eb1769f60e11b815233600482015230602482015287906001600160a01b0387169063dd62ed3e90604401602060405180830381865afa15801561199d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c191906125d4565b1015611a085760405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e7420616c6c6f77616e636560501b604482015260640161040c565b611a2d565b86341015611a2d5760405162461bcd60e51b815260040161040c906127dc565b60008815611a9057611a83886002548873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03168a6001600160a01b031614611a705733611a72565b305b6001546001600160a01b031661210f565b611a8d90826128eb565b90505b6001600160a01b03841615611b2c576113888310611ae75760405162461bcd60e51b81526020600482015260146024820152730caf0e8e4c28ccaca84e0e640e8dede40d0d2ced60631b604482015260640161040c565b611b1f8884886001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b175733611b19565b305b8861210f565b611b2990826128eb565b90505b6001600160a01b03861673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b6a57611b65863387611b60858d612903565b611f0c565b611be4565b60006001600160a01b038616611b80838b612903565b604051600081818185875af1925050503d8060008114611bbc576040519150601f19603f3d011682016040523d82523d6000602084013e611bc1565b606091505b5050905080611be25760405162461bcd60e51b815260040161040c9061291a565b505b846001600160a01b0316336001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac16888b858e604051611c2d9493929190612943565b60405180910390a360019150505b979650505050505050565b611c4e611cd0565b611c586000612326565b565b611c62611cd0565b6001600160a01b038116611cc75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161040c565b61049381612326565b6000546001600160a01b03163314611c585760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161040c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611d869190612b20565b6000604051808303816000865af19150503d8060008114611dc3576040519150601f19603f3d011682016040523d82523d6000602084013e611dc8565b606091505b5091509150818015611df2575080511580611df2575080806020019051810190611df29190612b3c565b611e235760405162461bcd60e51b815260206004820152600260248201526114d560f21b604482015260640161040c565b5050505050565b80516040820151600091829160045b60028110611eac57600086611e4f83600261279b565b60098110611e5f57611e5f6125ed565b60200201516001600160a01b031614611e9a5785611e7e82600261279b565b60098110611e8e57611e8e6125ed565b60200201519150611eac565b80611ea481612b59565b915050611e39565b506001600160a01b038116611f035760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420726f75746520706172616d65746572000000000000000000604482015260640161040c565b94909350915050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611f709190612b20565b6000604051808303816000865af19150503d8060008114611fad576040519150601f19603f3d011682016040523d82523d6000602084013e611fb2565b606091505b5091509150818015611fdc575080511580611fdc575080806020019051810190611fdc9190612b3c565b61200e5760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015260640161040c565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916120729190612b20565b6000604051808303816000865af19150503d80600081146120af576040519150601f19603f3d011682016040523d82523d6000602084013e6120b4565b606091505b50915091508180156120de5750805115806120de5750808060200190518101906120de9190612b3c565b611e235760405162461bcd60e51b8152602060048201526002602482015261534160f01b604482015260640161040c565b60008061211c8787610808565b9050801561228e576001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461217457306001600160a01b0385160361216857612163858483611d2a565b612287565b61216385858584611f0c565b6001600160a01b03841630146121e25760405162461bcd60e51b815260206004820152602d60248201527f63616e206f6e6c79207472616e73666572206574682066726f6d20746865207260448201526c6f75746572206164647265737360981b606482015260840161040c565b6000836001600160a01b03168260405160006040518083038185875af1925050503d806000811461222f576040519150601f19603f3d011682016040523d82523d6000602084013e612234565b606091505b50509050806122855760405162461bcd60e51b815260206004820152601e60248201527f7472616e73666572206661696c656420696e207472616e736665724665650000604482015260640161040c565b505b9050612294565b60009150505b95945050505050565b6000808080808560018111156122b5576122b5612a30565b036122db57858060200190518101906122ce9190612b70565b9193509091506122f99050565b858060200190518101906122ef9190612bbd565b9395509293505050505b90925090505b9250929050565b6000808280602001905181019061231d9190612b70565b50949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405180604001604052806002906020820280368337509192915050565b6001600160a01b038116811461049357600080fd5b6000602082840312156123bb57600080fd5b81356123c681612394565b9392505050565b806040810183101561082457600080fd5b600080606083850312156123f157600080fd5b6123fb84846123cd565b946040939093013593505050565b83815260a0810160208083018560005b600281101561243f5781516001600160a01b031683529183019190830190600101612419565b505050606083018460005b60028110156124675781518352918301919083019060010161244a565b50505050949350505050565b6000806040838503121561248657600080fd5b50508035926020909101359150565b600061046082840312156124a857600080fd5b50919050565b60005b838110156124c95781810151838201526020016124b1565b838111156124d8576000848401525b50505050565b600081518084526124f68160208601602086016124ae565b601f01601f19169290920160200192915050565b60208152600061082160208301846124de565b60006020828403121561252f57600080fd5b813567ffffffffffffffff81111561254657600080fd5b820161018081850312156123c657600080fd5b6000806000806000806000610100888a03121561257557600080fd5b873596506020880135955061258d8960408a016123cd565b9450608088013561259d81612394565b935060a08801356125ad81612394565b925060c08801356125bd81612394565b8092505060e0880135905092959891949750929550565b6000602082840312156125e657600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561261557600080fd5b815160ff811681146123c657600080fd5b634e487b7160e01b600052601160045260246000fd5b600181815b8085111561267757816000190482111561265d5761265d612626565b8085161561266a57918102915b93841c9390800290612641565b509250929050565b60008261268e57506001610824565b8161269b57506000610824565b81600181146126b157600281146126bb576126d7565b6001915050610824565b60ff8411156126cc576126cc612626565b50506001821b610824565b5060208310610133831016604e8410600b84101617156126fa575081810a610824565b612704838361263c565b806000190482111561271857612718612626565b029392505050565b6000610821838361267f565b805169ffffffffffffffffffff8116811461274657600080fd5b919050565b600080600080600060a0868803121561276357600080fd5b61276c8661272c565b945060208601519350604086015192506060860151915061278f6080870161272c565b90509295509295909350565b60008160001904831182151516156127b5576127b5612626565b500290565b6000826127d757634e487b7160e01b600052601260045260246000fd5b500490565b6020808252601b908201527f696e73756666696369656e742065746865722070726f76696465640000000000604082015260600190565b8060005b60048110156124d857813561282b81612394565b6001600160a01b031684526020938401939190910190600101612817565b610380810181886000805b600981101561288657823561286881612394565b6001600160a01b031684526020938401939290920191600101612854565b5061012085019250899150805b60048110156128b657606080848637938401828152939290920191600101612893565b50505050856102a0830152846102c08301526128d66102e0830185612813565b6001600160a01b038316610360830152611c3b565b600082198211156128fe576128fe612626565b500190565b60008282101561291557612915612626565b500390565b6020808252600f908201526e1d1c985b9cd9995c8819985a5b1959608a1b604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b801515811461049357600080fd5b60006020828403121561298957600080fd5b81356123c681612969565b600181811c908216806129a857607f821691505b6020821081036124a857634e487b7160e01b600052602260045260246000fd5b6000808335601e198436030181126129df57600080fd5b83018035915067ffffffffffffffff8211156129fa57600080fd5b6020019150368190038213156122ff57600080fd5b600060208284031215612a2157600080fd5b8135600281106123c657600080fd5b634e487b7160e01b600052602160045260246000fd5b62ffffff8116811461049357600080fd5b600080600080600060a08688031215612a6f57600080fd5b8535612a7a81612394565b94506020860135612a8a81612a46565b93506040860135612a9a81612394565b92506060860135612aaa81612a46565b91506080860135612aba81612394565b809150509295509295909350565b602081526000825160a06020840152612ae460c08401826124de565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b60008251612b328184602087016124ae565b9190910192915050565b600060208284031215612b4e57600080fd5b81516123c681612969565b600081612b6857612b68612626565b506000190190565b600080600060608486031215612b8557600080fd5b8351612b9081612394565b6020850151909350612ba181612a46565b6040850151909250612bb281612394565b809150509250925092565b600080600080600060a08688031215612bd557600080fd5b8551612be081612394565b6020870151909550612bf181612a46565b6040870151909450612c0281612394565b6060870151909350612c1381612a46565b6080870151909250612aba8161239456fe55f56a47af95f637819da860d955ff441e2d4c2a708c3608ead3781c68a63619a26469706673582212202bb95277c262b39de57c6b2e6f0cc9f50d3b4f1871c5638d83914af299f5333d64736f6c634300080d00330000000000000000000000005f0947253a8218894af13438ac2e2e0ced30d234000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000002a426b3bb4fa87488387545f15d01d81352732f90000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000000000000000000003302e320000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106101025760003560e01c806360dc2340116100955780638da5cb5b116100645780638da5cb5b146102b6578063bf5a5940146102d4578063cda90b88146102ea578063d55be8c61461030a578063f2fde38b1461032057600080fd5b806360dc23401461023e5780636404f8fe1461025e578063715018a614610281578063735de9f71461029657600080fd5b806334e73122116100d157806334e73122146101c8578063534ce2a5146101f657806354fd4d50146102095780636038ce651461022b57600080fd5b806301681a621461010e5780630d742ff71461013057806317fcb39b1461016857806331f7d964146101a057600080fd5b3661010957005b600080fd5b34801561011a57600080fd5b5061012e6101293660046123a9565b610340565b005b34801561013c57600080fd5b5061015061014b3660046123de565b610496565b60405161015f93929190612409565b60405180910390f35b34801561017457600080fd5b50600554610188906001600160a01b031681565b6040516001600160a01b03909116815260200161015f565b3480156101ac57600080fd5b5061018873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156101d457600080fd5b506101e86101e3366004612473565b610808565b60405190815260200161015f565b6101e8610204366004612495565b61082a565b34801561021557600080fd5b5061021e610e22565b60405161015f919061250a565b6101e861023936600461251d565b610eb0565b34801561024a57600080fd5b50600154610188906001600160a01b031681565b61027161026c366004612559565b611809565b604051901515815260200161015f565b34801561028d57600080fd5b5061012e611c46565b3480156102a257600080fd5b50600354610188906001600160a01b031681565b3480156102c257600080fd5b506000546001600160a01b0316610188565b3480156102e057600080fd5b506101e860025481565b3480156102f657600080fd5b50600454610188906001600160a01b031681565b34801561031657600080fd5b506101e861138881565b34801561032c57600080fd5b5061012e61033b3660046123a9565b611c5a565b610348611cd0565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03821601610419576001546040516000916001600160a01b03169047908381818185875af1925050503d80600081146103ba576040519150601f19603f3d011682016040523d82523d6000602084013e6103bf565b606091505b50509050806104155760405162461bcd60e51b815260206004820152601860248201527f7472616e73666572206661696c656420696e207377656570000000000000000060448201526064015b60405180910390fd5b5050565b6001546040516370a0823160e01b81523060048201526104939183916001600160a01b03918216918316906370a0823190602401602060405180830381865afa15801561046a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048e91906125d4565b611d2a565b50565b60006104a0612376565b6104a8612376565b60006104b760208701876123a9565b6001600160a01b03161415806104e6575060006104da60408701602088016123a9565b6001600160a01b031614155b6105275760405162461bcd60e51b8152602060048201526012602482015271696e76616c6964207072696365666565647360701b604482015260640161040c565b600080808061053960208a018a6123a9565b6001600160a01b031603610562576001925061055b6040890160208a016123a9565b91506105a4565b61056f60208901896123a9565b9150600061058360408a0160208b016123a9565b6001600160a01b0316146105a4576105a16040890160208a016123a9565b90505b6000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106089190612603565b6106169060ff16600a612720565b90506000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610658573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067c919061274b565b5050509150508086600060028110610696576106966125ed565b602002015284156106bd57806106ac838b61279b565b6106b691906127ba565b97506106d5565b816106c8828b61279b565b6106d291906127ba565b97505b6001600160a01b038316156107de57826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107469190612603565b6107549060ff16600a612720565b9150826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610794573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b8919061274b565b5050506020880181905291508190506107d1838a61279b565b6107db91906127ba565b97505b5050604080518082019091526001600160a01b039283168152911660208201529250509250925092565b6000612710610817838561279b565b61082191906127ba565b90505b92915050565b6004546000906001600160a01b03166108855760405162461bcd60e51b815260206004820152601860248201527f637572766520726f75746572206e6f742070726573656e740000000000000000604482015260640161040c565b6000806108bd8460a0016009806020026040519081016040528092919082600960200280828437600092019190915250611e2a915050565b90925090506000806108d76103e087016103c088016123a9565b6001600160a01b0316141580610908575060006108fc61040087016103e088016123a9565b6001600160a01b031614155b156109b757610915612376565b61091d612376565b61092f876103c0018860600135610496565b815181516040519081529396509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b0316156109b057602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b50506109be565b5060608401355b3415610a695784604001353410156109e85760405162461bcd60e51b815260040161040c906127dc565b600560009054906101000a90046001600160a01b03166001600160a01b031663d0e30db086604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a3c57600080fd5b505af1158015610a50573d6000803e3d6000fd5b50506005546001600160a01b03169450610a7992505050565b610a798233308860400135611f0c565b600454610a959083906001600160a01b03166040880135612016565b6004805460408051630651cb3560e01b81526000936001600160a01b0390931692630651cb3592610adf9260a08c01926101c08d01928d01359189916103408f0191309101612849565b6020604051808303816000875af1158015610afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2291906125d4565b90506000608087013515610b4957610b3c83600254610808565b610b4690826128eb565b90505b6000610b5d61042089016104008a016123a9565b6001600160a01b031614610be55761138887610420013510610bb55760405162461bcd60e51b81526020600482015260116024820152700caf0e8e4c28ccaca40e8dede40d0d2ced607b1b604482015260640161040c565b610bd883610420890180359088903090610bd3906104008e016123a9565b61210f565b610be290826128eb565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03861601610c97576000610c1c6040890160208a016123a9565b6001600160a01b0316610c2f8386612903565b604051600081818185875af1925050503d8060008114610c6b576040519150601f19603f3d011682016040523d82523d6000602084013e610c70565b606091505b5050905080610c915760405162461bcd60e51b815260040161040c9061291a565b50610cb5565b610cb585610cab60408a0160208b016123a9565b61048e8487612903565b610cc560408801602089016123a9565b6001600160a01b0316610cdb60208901896123a9565b6001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac168786858c60800135604051610d1d9493929190612943565b60405180910390a36000610d318484612903565b9050600081118015610d505750610d5061046089016104408a01612977565b15610e165773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601610dff576000610d8960208a018a6123a9565b6001600160a01b03168260405160006040518083038185875af1925050503d8060008114610dd3576040519150601f19603f3d011682016040523d82523d6000602084013e610dd8565b606091505b5050905080610df95760405162461bcd60e51b815260040161040c9061291a565b50610e16565b610e1686610e1060208b018b6123a9565b83611d2a565b50909695505050505050565b60068054610e2f90612994565b80601f0160208091040260200160405190810160405280929190818152602001828054610e5b90612994565b8015610ea85780601f10610e7d57610100808354040283529160200191610ea8565b820191906000526020600020905b815481529060010190602001808311610e8b57829003601f168201915b505050505081565b6003546000906001600160a01b0316610f0b5760405162461bcd60e51b815260206004820152601a60248201527f756e697377617020726f75746572206e6f742070726573656e74000000000000604482015260640161040c565b600080610f6a610f1e60a08601866129c8565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610f659250505061018087016101608801612a0f565b61229d565b909250905060008080610f8360e0880160c089016123a9565b6001600160a01b0316141580610fb357506000610fa7610100880160e089016123a9565b6001600160a01b031614155b1561106157610fc0612376565b610fc8612376565b610fd98860c0018960600135610496565b815181516040519081529396509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b03161561105a57602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b5050611068565b5060608501355b34156111135785604001353410156110925760405162461bcd60e51b815260040161040c906127dc565b600560009054906101000a90046001600160a01b03166001600160a01b031663d0e30db087604001356040518263ffffffff1660e01b81526004016000604051808303818588803b1580156110e657600080fd5b505af11580156110fa573d6000803e3d6000fd5b50506005546001600160a01b0316955061112392505050565b6111238333308960400135611f0c565b60035461113f9084906001600160a01b03166040890135612016565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0386160161117857506005546001600160a01b0316935060015b600061118c61018089016101608a01612a0f565b600181111561119d5761119d612a30565b036113165760006111ee6111b460a08a018a6129c8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061230692505050565b60408051610100810182526001600160a01b038089168252898116602083015262ffffff84168284015230606083015242608083015260a082018790528b83013560c0830152600060e08301526003549251631b67c43360e31b8152939450909291169063db3e2198906112ca90849060040181516001600160a01b03908116825260208084015182169083015260408084015162ffffff16908301526060808401518216908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b6020604051808303816000875af11580156112e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130d91906125d4565b9450505061143b565b6000808061132760a08b018b6129c8565b8101906113349190612a57565b506040805160a0810182526bffffffffffffffffffffffff1960608f811b821660c08401526001600160e81b031960e888811b821660d486015287831b841660d786015286901b1660eb8401528e811b90911660ee830152825180830360e2018152610102830184528252306020830152428284015281018b90528f82013560808201526003549151631e51809360e31b81529498509296509094509092506001600160a01b03169063f28c0498906113f1908490600401612ac8565b6020604051808303816000875af1158015611410573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143491906125d4565b9650505050505b80156114b757600554604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561148757600080fd5b505af115801561149b573d6000803e3d6000fd5b5050505073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee94505b60006080880135156114dc576114cf83600254610808565b6114d990826128eb565b90505b60006114f06101208a016101008b016123a9565b6001600160a01b03161461157357611388886101200135106115485760405162461bcd60e51b81526020600482015260116024820152700caf0e8e4c28ccaca40e8dede40d0d2ced607b1b604482015260640161040c565b611566836101208a0180359089903090610bd3906101008f016123a9565b61157090826128eb565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038716016116255760006115aa60408a0160208b016123a9565b6001600160a01b03166115bd8386612903565b604051600081818185875af1925050503d80600081146115f9576040519150601f19603f3d011682016040523d82523d6000602084013e6115fe565b606091505b505090508061161f5760405162461bcd60e51b815260040161040c9061291a565b50611639565b61163986610cab60408b0160208c016123a9565b6116496040890160208a016123a9565b6001600160a01b031661165f60208a018a6123a9565b6001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac168886858d608001356040516116a19493929190612943565b60405180910390a36003546116c29086906001600160a01b03166000612016565b8760400135841080156116e857506116e261016089016101408a01612977565b15156001145b156117fd5760006116fd8560408b0135612903565b905034156117ea57600554604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561174b57600080fd5b505af115801561175f573d6000803e3d6000fd5b506000925061177491505060208b018b6123a9565b6001600160a01b03168260405160006040518083038185875af1925050503d80600081146117be576040519150601f19603f3d011682016040523d82523d6000602084013e6117c3565b606091505b50509050806117e45760405162461bcd60e51b815260040161040c9061291a565b506117fb565b6117fb86610e1060208c018c6123a9565b505b50919695505050505050565b60008660000361184c5760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b604482015260640161040c565b600061185b60208801886123a9565b6001600160a01b031614158061188a5750600061187e60408801602089016123a9565b6001600160a01b031614155b1561192d57611897612376565b61189f612376565b6118a9888a610496565b81518151604051908152939c509094509092506001600160a01b031690600080516020612c258339815191529060200160405180910390a260208101516001600160a01b03161561192a57602080820151838201516040519081526001600160a01b0390911691600080516020612c25833981519152910160405180910390a25b50505b6001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611a0d57604051636eb1769f60e11b815233600482015230602482015287906001600160a01b0387169063dd62ed3e90604401602060405180830381865afa15801561199d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c191906125d4565b1015611a085760405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e7420616c6c6f77616e636560501b604482015260640161040c565b611a2d565b86341015611a2d5760405162461bcd60e51b815260040161040c906127dc565b60008815611a9057611a83886002548873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03168a6001600160a01b031614611a705733611a72565b305b6001546001600160a01b031661210f565b611a8d90826128eb565b90505b6001600160a01b03841615611b2c576113888310611ae75760405162461bcd60e51b81526020600482015260146024820152730caf0e8e4c28ccaca84e0e640e8dede40d0d2ced60631b604482015260640161040c565b611b1f8884886001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b175733611b19565b305b8861210f565b611b2990826128eb565b90505b6001600160a01b03861673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611b6a57611b65863387611b60858d612903565b611f0c565b611be4565b60006001600160a01b038616611b80838b612903565b604051600081818185875af1925050503d8060008114611bbc576040519150601f19603f3d011682016040523d82523d6000602084013e611bc1565b606091505b5050905080611be25760405162461bcd60e51b815260040161040c9061291a565b505b846001600160a01b0316336001600160a01b03167f25f5a9cc9bfe1682a580e95d1f73b373aacdb5f8ae2009a32e67fdc4c79aac16888b858e604051611c2d9493929190612943565b60405180910390a360019150505b979650505050505050565b611c4e611cd0565b611c586000612326565b565b611c62611cd0565b6001600160a01b038116611cc75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161040c565b61049381612326565b6000546001600160a01b03163314611c585760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161040c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611d869190612b20565b6000604051808303816000865af19150503d8060008114611dc3576040519150601f19603f3d011682016040523d82523d6000602084013e611dc8565b606091505b5091509150818015611df2575080511580611df2575080806020019051810190611df29190612b3c565b611e235760405162461bcd60e51b815260206004820152600260248201526114d560f21b604482015260640161040c565b5050505050565b80516040820151600091829160045b60028110611eac57600086611e4f83600261279b565b60098110611e5f57611e5f6125ed565b60200201516001600160a01b031614611e9a5785611e7e82600261279b565b60098110611e8e57611e8e6125ed565b60200201519150611eac565b80611ea481612b59565b915050611e39565b506001600160a01b038116611f035760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420726f75746520706172616d65746572000000000000000000604482015260640161040c565b94909350915050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611f709190612b20565b6000604051808303816000865af19150503d8060008114611fad576040519150601f19603f3d011682016040523d82523d6000602084013e611fb2565b606091505b5091509150818015611fdc575080511580611fdc575080806020019051810190611fdc9190612b3c565b61200e5760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015260640161040c565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916120729190612b20565b6000604051808303816000865af19150503d80600081146120af576040519150601f19603f3d011682016040523d82523d6000602084013e6120b4565b606091505b50915091508180156120de5750805115806120de5750808060200190518101906120de9190612b3c565b611e235760405162461bcd60e51b8152602060048201526002602482015261534160f01b604482015260640161040c565b60008061211c8787610808565b9050801561228e576001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461217457306001600160a01b0385160361216857612163858483611d2a565b612287565b61216385858584611f0c565b6001600160a01b03841630146121e25760405162461bcd60e51b815260206004820152602d60248201527f63616e206f6e6c79207472616e73666572206574682066726f6d20746865207260448201526c6f75746572206164647265737360981b606482015260840161040c565b6000836001600160a01b03168260405160006040518083038185875af1925050503d806000811461222f576040519150601f19603f3d011682016040523d82523d6000602084013e612234565b606091505b50509050806122855760405162461bcd60e51b815260206004820152601e60248201527f7472616e73666572206661696c656420696e207472616e736665724665650000604482015260640161040c565b505b9050612294565b60009150505b95945050505050565b6000808080808560018111156122b5576122b5612a30565b036122db57858060200190518101906122ce9190612b70565b9193509091506122f99050565b858060200190518101906122ef9190612bbd565b9395509293505050505b90925090505b9250929050565b6000808280602001905181019061231d9190612b70565b50949350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405180604001604052806002906020820280368337509192915050565b6001600160a01b038116811461049357600080fd5b6000602082840312156123bb57600080fd5b81356123c681612394565b9392505050565b806040810183101561082457600080fd5b600080606083850312156123f157600080fd5b6123fb84846123cd565b946040939093013593505050565b83815260a0810160208083018560005b600281101561243f5781516001600160a01b031683529183019190830190600101612419565b505050606083018460005b60028110156124675781518352918301919083019060010161244a565b50505050949350505050565b6000806040838503121561248657600080fd5b50508035926020909101359150565b600061046082840312156124a857600080fd5b50919050565b60005b838110156124c95781810151838201526020016124b1565b838111156124d8576000848401525b50505050565b600081518084526124f68160208601602086016124ae565b601f01601f19169290920160200192915050565b60208152600061082160208301846124de565b60006020828403121561252f57600080fd5b813567ffffffffffffffff81111561254657600080fd5b820161018081850312156123c657600080fd5b6000806000806000806000610100888a03121561257557600080fd5b873596506020880135955061258d8960408a016123cd565b9450608088013561259d81612394565b935060a08801356125ad81612394565b925060c08801356125bd81612394565b8092505060e0880135905092959891949750929550565b6000602082840312156125e657600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561261557600080fd5b815160ff811681146123c657600080fd5b634e487b7160e01b600052601160045260246000fd5b600181815b8085111561267757816000190482111561265d5761265d612626565b8085161561266a57918102915b93841c9390800290612641565b509250929050565b60008261268e57506001610824565b8161269b57506000610824565b81600181146126b157600281146126bb576126d7565b6001915050610824565b60ff8411156126cc576126cc612626565b50506001821b610824565b5060208310610133831016604e8410600b84101617156126fa575081810a610824565b612704838361263c565b806000190482111561271857612718612626565b029392505050565b6000610821838361267f565b805169ffffffffffffffffffff8116811461274657600080fd5b919050565b600080600080600060a0868803121561276357600080fd5b61276c8661272c565b945060208601519350604086015192506060860151915061278f6080870161272c565b90509295509295909350565b60008160001904831182151516156127b5576127b5612626565b500290565b6000826127d757634e487b7160e01b600052601260045260246000fd5b500490565b6020808252601b908201527f696e73756666696369656e742065746865722070726f76696465640000000000604082015260600190565b8060005b60048110156124d857813561282b81612394565b6001600160a01b031684526020938401939190910190600101612817565b610380810181886000805b600981101561288657823561286881612394565b6001600160a01b031684526020938401939290920191600101612854565b5061012085019250899150805b60048110156128b657606080848637938401828152939290920191600101612893565b50505050856102a0830152846102c08301526128d66102e0830185612813565b6001600160a01b038316610360830152611c3b565b600082198211156128fe576128fe612626565b500190565b60008282101561291557612915612626565b500390565b6020808252600f908201526e1d1c985b9cd9995c8819985a5b1959608a1b604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b801515811461049357600080fd5b60006020828403121561298957600080fd5b81356123c681612969565b600181811c908216806129a857607f821691505b6020821081036124a857634e487b7160e01b600052602260045260246000fd5b6000808335601e198436030181126129df57600080fd5b83018035915067ffffffffffffffff8211156129fa57600080fd5b6020019150368190038213156122ff57600080fd5b600060208284031215612a2157600080fd5b8135600281106123c657600080fd5b634e487b7160e01b600052602160045260246000fd5b62ffffff8116811461049357600080fd5b600080600080600060a08688031215612a6f57600080fd5b8535612a7a81612394565b94506020860135612a8a81612a46565b93506040860135612a9a81612394565b92506060860135612aaa81612a46565b91506080860135612aba81612394565b809150509295509295909350565b602081526000825160a06020840152612ae460c08401826124de565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b60008251612b328184602087016124ae565b9190910192915050565b600060208284031215612b4e57600080fd5b81516123c681612969565b600081612b6857612b68612626565b506000190190565b600080600060608486031215612b8557600080fd5b8351612b9081612394565b6020850151909350612ba181612a46565b6040850151909250612bb281612394565b809150509250925092565b600080600080600060a08688031215612bd557600080fd5b8551612be081612394565b6020870151909550612bf181612a46565b6040870151909450612c0281612394565b6060870151909350612c1381612a46565b6080870151909250612aba8161239456fe55f56a47af95f637819da860d955ff441e2d4c2a708c3608ead3781c68a63619a26469706673582212202bb95277c262b39de57c6b2e6f0cc9f50d3b4f1871c5638d83914af299f5333d64736f6c634300080d0033

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

0000000000000000000000005f0947253a8218894af13438ac2e2e0ced30d234000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000002a426b3bb4fa87488387545f15d01d81352732f90000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000000000000000000003302e320000000000000000000000000000000000000000000000000000000000

-----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): 0x2a426b3Bb4fa87488387545f15D01d81352732F9
Arg [5] : _wrappedNativeToken (address): 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000005f0947253a8218894af13438ac2e2e0ced30d234
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [3] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Arg [4] : 0000000000000000000000002a426b3bb4fa87488387545f15d01d81352732f9
Arg [5] : 0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270
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://2bb95277c262b39de57c6b2e6f0cc9f50d3b4f1871c5638d83914af299f5333d

Block Transaction 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.