Contract Address Details

0x1dC39829C9D9F698add8f919c7A1a43CF0276b7F

Contract Name
SwapController
Creator
0xa29568–16b72e at 0xb42b37–5a1a26
Balance
0 ASTR ( )
Tokens
Fetching tokens...
Transactions
2 Transactions
Transfers
33,709 Transfers
Gas Used
53,445
Last Balance Update
2438798
Contract name:
SwapController




Optimization enabled
true
Compiler version
v0.8.4+commit.c7e474f2




Optimization runs
99
EVM Version
default




Verified at
2022-04-28T13:16:18.654720Z

Constructor Arguments

4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572000000000000000000000000e915d2393a08a00c5a463053edd31bae2199b9e7000000000000000000000000a9473608514457b4bf083f9045fa63ae5810a03e00000000000000000000000043783ece7b46bb026d4cebfd3e29f539ff1914fb000000000000000000000000cf83a3d83c1265780d9374e8a7c838fe22bd3dc6000000000000000000000000cdb32eed99aa19d39e5d6ec45ba74dc4afec549f00000000000000000000000029f6e49c6e3397c3a84f715885f9f233a441165c0000000000000000000000006a2d262d56735dba19dd70682b39f6be9a931d98000000000000000000000000aeaaf0e2c81af264101b9129c00f4440ccf0f720

Arg [0] (address) : 0x6c6572206973206e6f7420746865206f776e6572
Arg [1] (address) : 0xe915d2393a08a00c5a463053edd31bae2199b9e7
Arg [2] (address) : 0xa9473608514457b4bf083f9045fa63ae5810a03e
Arg [3] (address) : 0x43783ece7b46bb026d4cebfd3e29f539ff1914fb
Arg [4] (address) : 0xcf83a3d83c1265780d9374e8a7c838fe22bd3dc6
Arg [5] (address) : 0xcdb32eed99aa19d39e5d6ec45ba74dc4afec549f
Arg [6] (address) : 0x29f6e49c6e3397c3a84f715885f9f233a441165c
Arg [7] (address) : 0x6a2d262d56735dba19dd70682b39f6be9a931d98

              

Contract source code

// Sources flattened with hardhat v2.8.4 https://hardhat.org

// File @uniswap/v2-core/contracts/interfaces/[email protected]

pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}


// File @uniswap/v2-core/contracts/interfaces/[email protected]

pragma solidity >=0.5.0;

interface IUniswapV2Factory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    function feeTo() external view returns (address);
    function feeToSetter() external view returns (address);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs(uint) external view returns (address pair);
    function allPairsLength() external view returns (uint);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
}


// File @openzeppelin/contracts/token/ERC20/[email protected]

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

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

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


// File @openzeppelin/contracts/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File @openzeppelin/contracts/token/ERC20/utils/[email protected]


// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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


// File contracts/interfaces/ISwapController.sol


pragma solidity 0.8.4;

interface ISwapController {
    function swapUsdcToOusd(uint256 _amount, uint256 _minOut) external;

    function swapUsdcToOru(uint256 _amount, uint256 _minOut) external;

    function swapOruToUsdc(uint256 _amount, uint256 _minOut) external;

    function swapOusdToUsdc(uint256 _amount, uint256 _minOut) external;

    function zapInOru(
        uint256 _amount,
        uint256 _minUsdc,
        uint256 _minLp
    ) external returns (uint256);

    function zapInUsdc(
        uint256 _amount,
        uint256 _minOru,
        uint256 _minLp
    ) external returns (uint256);

    function zapOutOru(uint256 _amount, uint256 _minOut)
        external
        returns (uint256);

    function swapWAstrToUsdc(uint256 _amount, uint256 _minOut) external;
}


// File contracts/interfaces/IUniswapV2Router.sol


pragma solidity 0.8.4;

interface IUniswapV2Router {
    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function removeLiquidity(  address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline) external returns(uint amountA, uint amountB);

    function swapExactTokensForETH(
        uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline
    ) external returns (uint[] memory amounts);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);

    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
    external
    payable
    returns (uint[] memory amounts);
}


// File @openzeppelin/contracts/utils/[email protected]


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

pragma solidity ^0.8.0;

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

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


// File @openzeppelin/contracts/access/[email protected]


// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

/**
 * @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 Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

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

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

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


// File @openzeppelin/contracts/security/[email protected]


// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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


// File @openzeppelin/contracts/utils/math/[email protected]


// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}


// File contracts/common/OrcusProtocol.sol


pragma solidity 0.8.4;
contract OrcusProtocol is Ownable, ReentrancyGuard {
    uint256 internal constant RATIO_PRECISION = 1e6;
    uint256 internal constant PRICE_PRECISION = 1e6;
    uint256 internal constant USDC_PRECISION = 1e6;
    uint256 internal constant MISSING_PRECISION = 1e12;
    uint256 internal constant OUSD_PRECISION = 1e18;
    uint256 internal constant ORU_PRECISION = 1e18;
    uint256 internal constant SWAP_FEE_PRECISION = 1e4;

    address internal constant ADDRESS_USDC =
        0x6a2d262D56735DbA19Dd70682B39F6bE9a931D98;
    address internal constant ADDRESS_WASTR =
        0xAeaaf0e2c81Af264101B9129C00F4440cCF0F720;

    address public operator;

    event OperatorUpdated(address indexed newOperator);

    constructor() {
        setOperator(msg.sender);
    }

    modifier onlyNonContract() {
        require(msg.sender == tx.origin, "Orcus: sender != origin");
        _;
    }

    modifier onlyOwnerOrOperator() {
        require(
            msg.sender == owner() || msg.sender == operator,
            "Orcus: sender != operator"
        );
        _;
    }

    function setOperator(address _operator) public onlyOwner {
        require(_operator != address(0), "Orcus: Invalid operator");
        operator = _operator;
        emit OperatorUpdated(operator);
    }

    function _currentBlockTs() internal view returns (uint64) {
        return SafeCast.toUint64(block.timestamp);
    }
}


// File contracts/libraries/TransferHelper.sol



pragma solidity >=0.6.0;

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::safeApprove: approve failed'
        );
    }

    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::safeTransfer: transfer failed'
        );
    }

    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::transferFrom: transferFrom failed'
        );
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
    }
}


// File hardhat/[email protected]


pragma solidity >= 0.4.22 <0.9.0;

library console {
	address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

	function _sendLogPayload(bytes memory payload) private view {
		uint256 payloadLength = payload.length;
		address consoleAddress = CONSOLE_ADDRESS;
		assembly {
			let payloadStart := add(payload, 32)
			let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
		}
	}

	function log() internal view {
		_sendLogPayload(abi.encodeWithSignature("log()"));
	}

	function logInt(int p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
	}

	function logUint(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function logString(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function logBool(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function logAddress(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function logBytes(bytes memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
	}

	function logBytes1(bytes1 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
	}

	function logBytes2(bytes2 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
	}

	function logBytes3(bytes3 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
	}

	function logBytes4(bytes4 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
	}

	function logBytes5(bytes5 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
	}

	function logBytes6(bytes6 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
	}

	function logBytes7(bytes7 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
	}

	function logBytes8(bytes8 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
	}

	function logBytes9(bytes9 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
	}

	function logBytes10(bytes10 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
	}

	function logBytes11(bytes11 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
	}

	function logBytes12(bytes12 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
	}

	function logBytes13(bytes13 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
	}

	function logBytes14(bytes14 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
	}

	function logBytes15(bytes15 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
	}

	function logBytes16(bytes16 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
	}

	function logBytes17(bytes17 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
	}

	function logBytes18(bytes18 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
	}

	function logBytes19(bytes19 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
	}

	function logBytes20(bytes20 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
	}

	function logBytes21(bytes21 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
	}

	function logBytes22(bytes22 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
	}

	function logBytes23(bytes23 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
	}

	function logBytes24(bytes24 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
	}

	function logBytes25(bytes25 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
	}

	function logBytes26(bytes26 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
	}

	function logBytes27(bytes27 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
	}

	function logBytes28(bytes28 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
	}

	function logBytes29(bytes29 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
	}

	function logBytes30(bytes30 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
	}

	function logBytes31(bytes31 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
	}

	function logBytes32(bytes32 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
	}

	function log(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function log(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function log(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function log(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function log(uint p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
	}

	function log(uint p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
	}

	function log(uint p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
	}

	function log(uint p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
	}

	function log(string memory p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
	}

	function log(string memory p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
	}

	function log(string memory p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
	}

	function log(string memory p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
	}

	function log(bool p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
	}

	function log(bool p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
	}

	function log(bool p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
	}

	function log(bool p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
	}

	function log(address p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
	}

	function log(address p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
	}

	function log(address p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
	}

	function log(address p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
	}

	function log(uint p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
	}

	function log(uint p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
	}

	function log(uint p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
	}

	function log(uint p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
	}

	function log(uint p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
	}

	function log(uint p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
	}

	function log(uint p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
	}

	function log(uint p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
	}

	function log(uint p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
	}

	function log(uint p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
	}

	function log(uint p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
	}

	function log(uint p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
	}

	function log(string memory p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
	}

	function log(string memory p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
	}

	function log(string memory p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
	}

	function log(string memory p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
	}

	function log(bool p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
	}

	function log(bool p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
	}

	function log(bool p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
	}

	function log(bool p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
	}

	function log(bool p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
	}

	function log(bool p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
	}

	function log(bool p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
	}

	function log(bool p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
	}

	function log(bool p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
	}

	function log(bool p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
	}

	function log(bool p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
	}

	function log(bool p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
	}

	function log(address p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
	}

	function log(address p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
	}

	function log(address p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
	}

	function log(address p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
	}

	function log(address p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
	}

	function log(address p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
	}

	function log(address p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
	}

	function log(address p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
	}

	function log(address p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
	}

	function log(address p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
	}

	function log(address p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
	}

	function log(address p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
	}

	function log(address p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
	}

	function log(address p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
	}

	function log(address p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
	}

	function log(address p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
	}

	function log(uint p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
	}

}


// File contracts/common/SwapController.sol


pragma solidity 0.8.4;
interface IWETH {
    function deposit() external payable;
    function transfer(address to, uint value) external returns (bool);
    function withdraw(uint) external;
    function balanceOf(address account) external view returns (uint256);
}

library Babylonian {
    function sqrt(uint256 y) internal pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
        // else z = 0
    }
}

library SafeMath {
    function add(uint x, uint y) internal pure returns (uint z) {
        require((z = x + y) >= x, 'ds-math-add-overflow');
    }

    function sub(uint x, uint y) internal pure returns (uint z) {
        require((z = x - y) <= x, 'ds-math-sub-underflow');
    }

    function mul(uint x, uint y) internal pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
    }
    function div(uint a, uint b) internal pure returns (uint c) {
        require(b > 0, 'ds-math-division-by-zero');
        c = a / b;
    }
}

contract SwapController is ISwapController, OrcusProtocol {
    using SafeERC20 for IERC20;
    using SafeMath for uint;

    uint256 private constant TIMEOUT = 300;

    IUniswapV2Router public fbRouter;
    IUniswapV2Factory public fbFactory;
    IUniswapV2Pair public fbOruPair;
    IUniswapV2Pair public fbOusdPair;

    address public WBNB;  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


    uint public maxResidual = 100; // 1%, set 10000 to disable

    IERC20 public oru;
    IERC20 public ousd;
    IERC20 public usdc;
    IERC20 public wastr;

    address[] public fbOruPairPath;
    address[] public fbOusdPairPath;
    address[] public fbWAstrPairPath;

    address[] public fbUsdcOruPairPath;
    address[] public fbUsdcOusdPairPath;
    address[] public fbUsdcWAstrPairPath;

    uint8[] private fbDexIdsFB;
    uint8[] private fbDexIdsQuick;

    event LogSetContracts(
        address fbRouter,
        address fbFactory,
        address fbOruPair,
        address fbOusdPair
    );
    event LogSetPairPaths(
        address[] fbOruPairPath,
        address[] fbOusdPairPath,
        address[] fbWAstrPairPath
    );
    event LogSetDexIds(uint8[] fbDexIdsFB, uint8[] fbDexIdsQuick);

    constructor(
        address _router,
        address _factory,
        address _OruPair,
        address _OusdPair,
    //address _WAstrPair, // 0x6e7a5FAFcec6BB1e78bAE2A1F0B612012BF14827
        address _oru,
        address _ousd,
        address _usdc, // 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
        address _wastr // 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270
    ) {
        require(
            _router != address(0) &&
            _factory != address(0) &&
            _OruPair != address(0) &&
            _OusdPair != address(0),
            "Swap: Invalid Address"
        );

        setContracts( _router, _factory, _OruPair, _OusdPair);

        console.log("oUSD swap controller address %s", _ousd);

        address[] memory _OruPairPath = new address[](2);
        _OruPairPath[0] = _oru;
        _OruPairPath[1] = _usdc;
        address[] memory _OusdPairPath = new address[](2);
        _OusdPairPath[0] = _ousd;
        _OusdPairPath[1] = _usdc;
        address[] memory _WAstrPairPath = new address[](2);
        _WAstrPairPath[0] = _wastr;
        _WAstrPairPath[1] = _usdc;
        setPairPaths(_OruPairPath, _OusdPairPath, _WAstrPairPath);

        fbUsdcOruPairPath = [_usdc, _oru];
        fbUsdcOusdPairPath = [_usdc, _ousd];
        fbUsdcWAstrPairPath = [_usdc, _wastr];

        uint8[] memory _fbDexIdsFB = new uint8[](1);
        _fbDexIdsFB[0] = 0;
        uint8[] memory _fbDexIdsQuick = new uint8[](1);
        _fbDexIdsQuick[0] = 1;
        setDexIds(_fbDexIdsFB, _fbDexIdsQuick);

        oru = IERC20(_oru);
        ousd = IERC20(_ousd);
        usdc = IERC20(_usdc);
        wastr = IERC20(_wastr);

        WBNB = _wastr;
    }

    // Swap functions
    function swapUsdcToOusd(uint256 _amount, uint256 _minOut)
    external
    override
    nonReentrant
    {

        usdc.safeTransferFrom(msg.sender, address(this), _amount);
        usdc.safeApprove(address(fbRouter), 0);
        usdc.safeApprove(address(fbRouter), _amount);

        uint balancethis = usdc.balanceOf(address(this));



//        console.log(fb)

        console.log("4 here");
        console.log("swap controller usdc balance %s", balancethis);

        (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = fbOusdPair.getReserves();

        console.log("Reserves after callback 0 %s", reserve0);
        console.log("Reserves after callback 1 %s", reserve1);

//        console.log("_amount %s", _amount);
//        console.log("_minOut %s", _minOut);
//        console.log("_fbUSDC PAIR [0] %s", fbUsdcOusdPairPath[0]);
//        console.log("_fbUSDC PAIR [1] %s", fbUsdcOusdPairPath[1]);
//        console.log("msg.sender is %s", msg.sender);
//        console.log("last parameter %s", block.timestamp + TIMEOUT);

        fbRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            _amount,
            _minOut,
            fbUsdcOusdPairPath,
            msg.sender,
            block.timestamp + TIMEOUT
        );
    }

    function swapUsdcToOru(uint256 _amount, uint256 _minOut)
    external
    override
    nonReentrant
    {
        usdc.safeTransferFrom(msg.sender, address(this), _amount);
        usdc.safeApprove(address(fbRouter), 0);
        usdc.safeApprove(address(fbRouter), _amount);

        fbRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            _amount,
            _minOut,
            fbUsdcOruPairPath,
            msg.sender,
            block.timestamp + TIMEOUT
        );
    }

    function swapOruToUsdc(uint256 _amount, uint256 _minOut)
    external
    override
    nonReentrant
    {
        oru.safeTransferFrom(msg.sender, address(this), _amount);
        oru.safeApprove(address(fbRouter), 0);
        oru.safeApprove(address(fbRouter), _amount);

        console.log("wtf we here");

        fbRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            _amount,
            _minOut,
            fbOruPairPath,
            msg.sender,
            block.timestamp + TIMEOUT
        );
    }

    function swapOusdToUsdc(uint256 _amount, uint256 _minOut)
    external
    override
    nonReentrant
    {
        ousd.safeTransferFrom(msg.sender, address(this), _amount);
        ousd.safeApprove(address(fbRouter), 0);
        ousd.safeApprove(address(fbRouter), _amount);

        fbRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            _amount,
            _minOut,
            fbOusdPairPath,
            msg.sender,
            block.timestamp + TIMEOUT
        );
    }

    function swapWAstrToUsdc(uint256 _amount, uint256 _minOut)
    external
    override
    nonReentrant
    {
        wastr.safeTransferFrom(msg.sender, address(this), _amount);
        wastr.safeApprove(address(fbRouter), 0);
        wastr.safeApprove(address(fbRouter), _amount);

        fbRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            _amount,
            _minOut,
            fbWAstrPairPath,
            msg.sender,
            block.timestamp + TIMEOUT
        );
    }

    function zapInOru(
        uint256 _amount,
        uint256 _minUsdc,
        uint256 _minLp
    ) external override nonReentrant returns (uint256) {


        oru.safeTransferFrom(msg.sender, address(this), _amount);

        uint256[] memory _amounts = new uint256[](3);
        _amounts[0] = _amount; // amount_from (ORU)
        _amounts[1] = _minUsdc; // minTokenB (USDC)
        _amounts[2] = _minLp; // minLp

        uint256 _lpAmount = _zapInToken(
            address(oru),
            _amounts,
            address(fbOruPair),
            true
        );



        require(_lpAmount > 0, "Swap: No lp");
        require(
            fbOruPair.transfer(msg.sender, _lpAmount),
            "Swap: Faild to transfer"
        );

        return _lpAmount;
    }

    function zapInUsdc(
        uint256 _amount,
        uint256 _minOru,
        uint256 _minLp
    ) external override nonReentrant returns (uint256) {
        usdc.safeTransferFrom(msg.sender, address(this), _amount);

        uint256[] memory _amounts = new uint256[](3);
        _amounts[0] = _amount; // amount_from (USDC)
        _amounts[1] = _minOru; // minTokenB (ORU)
        _amounts[2] = _minLp; // minLp

        uint256 _lpAmount = _zapInToken(
            address(usdc),
            _amounts,
            address(fbOruPair),
            true
        );

        require(_lpAmount > 0, "Swap: No lp");
        require(
            fbOruPair.transfer(msg.sender, _lpAmount),
            "Swap: Faild to transfer"
        );

        return _lpAmount;
    }

    function zapOutOru(uint256 _amount, uint256 _minOut)
    external
    override
    nonReentrant
    returns (uint256)
    {
        require(
            fbOruPair.transferFrom(msg.sender, address(this), _amount),
            "Swap: Failed to transfer pair"
        );


        uint256 _oruAmount = _zapOut(
            address(fbOruPair),
            _amount,
            address(oru),
            _minOut
        );



        require(_oruAmount > 0, "Swap: Oru amount is 0");
        oru.safeTransfer(msg.sender, _oruAmount);
        return _oruAmount;
    }

    // Setters
    function setContracts(
        address _router,
        address _factory,
        address _OruPair,
        address _OusdPair
    ) public onlyOwner {

        if (_router != address(0)) {
            fbRouter = IUniswapV2Router(_router);
        }
        if (_factory != address(0)) {
            fbFactory = IUniswapV2Factory(_factory);
        }
        if (_OruPair != address(0)) {
            fbOruPair = IUniswapV2Pair(_OruPair);
        }
        if (_OusdPair != address(0)) {
            fbOusdPair = IUniswapV2Pair(_OusdPair);
        }

        emit LogSetContracts(
            _router,
            _factory,
            _OruPair,
            _OusdPair
        );
    }

    function setPairPaths(
        address[] memory _OruPairPath,
        address[] memory _OusdPairPath,
        address[] memory _WAstrPairPath
    ) public onlyOwner {
        fbOruPairPath = _OruPairPath;
        fbOusdPairPath = _OusdPairPath;
        fbWAstrPairPath = _WAstrPairPath;

        emit LogSetPairPaths(fbOruPairPath, fbOusdPairPath, fbWAstrPairPath);
    }

    function setDexIds(
        uint8[] memory _fbDexIdsFB,
        uint8[] memory _fbDexIdsQuick
    ) public onlyOwner {
        fbDexIdsFB = _fbDexIdsFB;
        fbDexIdsQuick = _fbDexIdsQuick;

        emit LogSetDexIds(fbDexIdsFB, fbDexIdsQuick);
    }

    function _zapInToken(address _from, uint[] memory amounts, address _to, bool transferResidual) private returns (uint256 lpAmt) {
        _approveTokenIfNeeded(_from);

        if (_from == IUniswapV2Pair(_to).token0() || _from == IUniswapV2Pair(_to).token1()) {
            // swap half amount for other
            address other;
            uint256 sellAmount;
            {
                address token0 = IUniswapV2Pair(_to).token0();
                address token1 = IUniswapV2Pair(_to).token1();
                other = _from == token0 ? token1 : token0;
                sellAmount = calculateSwapInAmount(_to, _from, amounts[0], token0);
            }
            uint otherAmount = _swap(_from, sellAmount, other, address(this), _to);
            require(otherAmount >= amounts[1], "Zap: Insufficient Receive Amount");


            lpAmt = _pairDeposit(_to, _from, other, amounts[0].sub(sellAmount), otherAmount, address(this), false, transferResidual);

        } else {
            uint bnbAmount = _swapTokenForBNB(_from, amounts[0], address(this), address(0));
            lpAmt = _swapBNBToLp(IUniswapV2Pair(_to), bnbAmount, address(this), 0, transferResidual);
        }

        require(lpAmt >= amounts[2], "Zap: High Slippage In");
        return lpAmt;
    }

    function _zapOut (address _from, uint amount, address _toToken, uint256 _minTokensRec) private returns (uint256) {
        _approveTokenIfNeeded(_from);

        address token0;
        address token1;
        uint256 amountA;
        uint256 amountB;
        {
            IUniswapV2Pair pair = IUniswapV2Pair(_from);
            token0 = pair.token0();
            token1 = pair.token1();
            (amountA, amountB) = fbRouter.removeLiquidity(token0, token1, amount, 0, 0, address(this), block.timestamp);
        }

        uint256 tokenBought;
        _approveTokenIfNeeded(token0);
        _approveTokenIfNeeded(token1);
        if (_toToken == WBNB) {
            address _lpOfFromAndTo = WBNB == token0 || WBNB == token1 ? _from : address(0);
            tokenBought = _swapTokenForBNB(token0, amountA, address(this), _lpOfFromAndTo);
            tokenBought = tokenBought + (_swapTokenForBNB(token1, amountB, address(this), _lpOfFromAndTo));
        } else {
            address _lpOfFromAndTo = _toToken == token0 || _toToken == token1 ? _from : address(0);
            tokenBought = _swap(token0, amountA, _toToken, address(this), _lpOfFromAndTo);
            tokenBought = tokenBought + (_swap(token1, amountB, _toToken, address(this), _lpOfFromAndTo));

        }





        require(tokenBought >= _minTokensRec, "Zap: High Slippage Out");
        if (_toToken == WBNB) {
            TransferHelper.safeTransferETH(address(this), tokenBought);
        } else {
            IERC20(_toToken).safeTransfer(address(this), tokenBought);
        }

        return tokenBought;
    }

    function _approveTokenIfNeeded(address token) private {
        if (IERC20(token).allowance(address(this), address(fbRouter)) == 0) {
            IERC20(token).safeApprove(address(fbRouter), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        }
    }


    function _swapTokenForBNB(address token, uint amount, address _receiver, address lpTokenBNB) private returns (uint) {
        if (token == WBNB) {
            _transferToken(WBNB, _receiver, amount);
            return amount;
        }

        address[] memory path = new address[](2);
        path[0] = token;
        path[1] = WBNB;
        uint[] memory amounts;
        if (path.length > 0) {
            amounts = fbRouter.swapExactTokensForETH(amount, 1, path, _receiver, block.timestamp);
        } else if (lpTokenBNB != address(0)) {
            path = new address[](1);
            path[0] = lpTokenBNB;
            amounts = fbRouter.swapExactTokensForETH(amount, 1, path, _receiver, block.timestamp);
        } else {
            revert("FireBirdZap: !path TokenBNB");
        }

        return amounts[amounts.length - 1];
    }

    function _swap(address _from, uint _amount, address _to, address _receiver, address _lpOfFromTo) internal returns (uint) {
        if (_from == _to) {
            if (_receiver != address(this)) {
                IERC20(_from).safeTransfer(_receiver, _amount);
            }
            return _amount;
        }
        address[] memory path = new address[](2);
        path[0] = _from;
        path[1] = _to;
        uint[] memory amounts;
        if (path.length > 0) {// use fireBird
            amounts = fbRouter.swapExactTokensForTokens(_amount, 1, path, _receiver, block.timestamp);
        } else if (_lpOfFromTo != address(0)) {
            path = new address[](1);
            path[0] = _lpOfFromTo;
            amounts = fbRouter.swapExactTokensForTokens(_amount, 1, path, _receiver, block.timestamp);
        } else {
            revert("FireBirdZap: !path swap");
        }

        return amounts[amounts.length - 1];
    }

    function _transferToken(address token, address to, uint amount) internal {
        if (amount == 0) {
            return;
        }

        if (token == WBNB) {
            IWETH(WBNB).withdraw(amount);
            if (to != address(this)) {
                TransferHelper.safeTransferETH(to, amount);
            }
        } else {
            IERC20(token).safeTransfer(to, amount);
        }
        return;
    }

    function calculateSwapInAmount(address pair, address tokenIn, uint256 userIn, address pairToken0) internal view returns (uint256) {
        (uint32 tokenWeight0, uint32 tokenWeight1) = (50,50); // ????????????????????????????
        uint swapFee = 0; // ?????????????????????
        if (tokenWeight0 == 50) {
            (uint256 res0, uint256 res1,) = IUniswapV2Pair(pair).getReserves();
            uint reserveIn = tokenIn == pairToken0 ? res0 : res1;
            uint256 rMul = uint256(10000).sub(uint256(swapFee));

            return _getExactSwapInAmount(reserveIn, userIn, rMul);
        } else {
            uint256 otherWeight = tokenIn == pairToken0 ? uint256(tokenWeight1) : uint256(tokenWeight0);
            return userIn.mul(otherWeight).div(100);
        }
    }

    function _getExactSwapInAmount(
        uint256 reserveIn,
        uint256 userIn,
        uint256 rMul
    ) internal pure returns (uint256) {
        return Babylonian.sqrt(reserveIn.mul(userIn.mul(40000).mul(rMul) + reserveIn.mul(rMul.add(10000)).mul(rMul.add(10000)))).sub(reserveIn.mul(rMul.add(10000))) / (rMul.mul(2));
    }

    function _pairDeposit(
        address _pair,
        address _poolToken0,
        address _poolToken1,
        uint256 token0Bought,
        uint256 token1Bought,
        address receiver,
        bool isfireBirdPair,
        bool transferResidual
    ) internal returns (uint256 lpAmt) {
        _approveTokenIfNeeded(_poolToken0);
        _approveTokenIfNeeded(_poolToken1);

        uint256 amountA;
        uint256 amountB;
        (amountA, amountB, lpAmt) = fbRouter.addLiquidity(_poolToken0, _poolToken1, token0Bought, token1Bought, 1, 1, receiver, block.timestamp);

        uint amountAResidual = token0Bought.sub(amountA);
        if (transferResidual || amountAResidual > token0Bought.mul(maxResidual).div(10000)) {
            if (amountAResidual > 0) {
                //Returning Residue in token0, if any.
                _transferToken(_poolToken0, msg.sender, amountAResidual);
            }
        }

        uint amountBRedisual = token1Bought.sub(amountB);
        if (transferResidual || amountBRedisual > token1Bought.mul(maxResidual).div(10000)) {
            if (amountBRedisual > 0) {
                //Returning Residue in token1, if any
                _transferToken(_poolToken1, msg.sender, amountBRedisual);
            }
        }

        return lpAmt;
    }

    function _swapBNBToLp(IUniswapV2Pair pair, uint amount, address receiver, uint _minTokenB, bool transferResidual) private returns (uint256 lpAmt) {
        address lp = address(pair);

        // Lp
        if (pair.token0() == WBNB || pair.token1() == WBNB) {
            address token = pair.token0() == WBNB ? pair.token1() : pair.token0();
            uint swapValue = calculateSwapInAmount(lp, WBNB, amount, pair.token0());
            uint tokenAmount = _swapBNBForToken(token, swapValue, address(this), lp);
            require(tokenAmount >= _minTokenB, "Zap: Insufficient Receive Amount");

            uint256 wbnbAmount = amount.sub(swapValue);
            IWETH(WBNB).deposit{value : wbnbAmount}();
            lpAmt = _pairDeposit(lp, WBNB, token, wbnbAmount, tokenAmount, receiver, false, transferResidual);
        } else {
            address token0 = pair.token0();
            address token1 = pair.token1();
            uint token0Amount;
            uint token1Amount;
            {
                uint32 tokenWeight0 = 50; // ??????????????????????
                uint swap0Value = amount.mul(uint(tokenWeight0)).div(100);
                token0Amount = _swapBNBForToken(token0, swap0Value, address(this), address(0));
                token1Amount = _swapBNBForToken(token1, amount.sub(swap0Value), address(this), address(0));
            }

            lpAmt = _pairDeposit(lp, token0, token1, token0Amount, token1Amount, receiver, false, transferResidual);
        }
    }

    function _swapBNBForToken(address token, uint value, address _receiver, address lpBNBToken) private returns (uint) {
        if (token == WBNB) {
            IWETH(WBNB).deposit{value : value}();
            if (_receiver != address(this)) {
                IERC20(WBNB).safeTransfer(_receiver, value);
            }
            return value;
        }
        address[] memory path = new address[](2);
        path[0] = WBNB;
        path[1] = token;
        uint[] memory amounts;
        if (path.length > 0) {
            amounts = fbRouter.swapExactETHForTokens{value : value}(1, path, _receiver, block.timestamp);
        } else if (lpBNBToken != address(0)) {
            path = new address[](1);
            path[0] = lpBNBToken;
            amounts = fbRouter.swapExactETHForTokens{value : value}(1, path, _receiver, block.timestamp);
        } else {
            revert("FireBirdZap: !path BNBToken");
        }

        return amounts[amounts.length - 1];
    }

}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_router","internalType":"address"},{"type":"address","name":"_factory","internalType":"address"},{"type":"address","name":"_OruPair","internalType":"address"},{"type":"address","name":"_OusdPair","internalType":"address"},{"type":"address","name":"_oru","internalType":"address"},{"type":"address","name":"_ousd","internalType":"address"},{"type":"address","name":"_usdc","internalType":"address"},{"type":"address","name":"_wastr","internalType":"address"}]},{"type":"event","name":"LogSetContracts","inputs":[{"type":"address","name":"fbRouter","internalType":"address","indexed":false},{"type":"address","name":"fbFactory","internalType":"address","indexed":false},{"type":"address","name":"fbOruPair","internalType":"address","indexed":false},{"type":"address","name":"fbOusdPair","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"LogSetDexIds","inputs":[{"type":"uint8[]","name":"fbDexIdsFB","internalType":"uint8[]","indexed":false},{"type":"uint8[]","name":"fbDexIdsQuick","internalType":"uint8[]","indexed":false}],"anonymous":false},{"type":"event","name":"LogSetPairPaths","inputs":[{"type":"address[]","name":"fbOruPairPath","internalType":"address[]","indexed":false},{"type":"address[]","name":"fbOusdPairPath","internalType":"address[]","indexed":false},{"type":"address[]","name":"fbWAstrPairPath","internalType":"address[]","indexed":false}],"anonymous":false},{"type":"event","name":"OperatorUpdated","inputs":[{"type":"address","name":"newOperator","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"WBNB","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Factory"}],"name":"fbFactory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Pair"}],"name":"fbOruPair","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fbOruPairPath","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Pair"}],"name":"fbOusdPair","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fbOusdPairPath","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Router"}],"name":"fbRouter","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fbUsdcOruPairPath","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fbUsdcOusdPairPath","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fbUsdcWAstrPairPath","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fbWAstrPairPath","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxResidual","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"operator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"oru","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"ousd","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setContracts","inputs":[{"type":"address","name":"_router","internalType":"address"},{"type":"address","name":"_factory","internalType":"address"},{"type":"address","name":"_OruPair","internalType":"address"},{"type":"address","name":"_OusdPair","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDexIds","inputs":[{"type":"uint8[]","name":"_fbDexIdsFB","internalType":"uint8[]"},{"type":"uint8[]","name":"_fbDexIdsQuick","internalType":"uint8[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOperator","inputs":[{"type":"address","name":"_operator","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPairPaths","inputs":[{"type":"address[]","name":"_OruPairPath","internalType":"address[]"},{"type":"address[]","name":"_OusdPairPath","internalType":"address[]"},{"type":"address[]","name":"_WAstrPairPath","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapOruToUsdc","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_minOut","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapOusdToUsdc","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_minOut","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapUsdcToOru","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_minOut","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapUsdcToOusd","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_minOut","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapWAstrToUsdc","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_minOut","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"usdc","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"wastr","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"zapInOru","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_minUsdc","internalType":"uint256"},{"type":"uint256","name":"_minLp","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"zapInUsdc","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_minOru","internalType":"uint256"},{"type":"uint256","name":"_minLp","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"zapOutOru","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_minOut","internalType":"uint256"}]}]
              

Contract Creation Code

0x608060405260646008553480156200001657600080fd5b506040516200570f3803806200570f833981016040819052620000399162000abd565b6200004433620004ef565b6001805562000053336200053f565b6001600160a01b038816158015906200007457506001600160a01b03871615155b80156200008957506001600160a01b03861615155b80156200009e57506001600160a01b03851615155b620000f05760405162461bcd60e51b815260206004820152601560248201527f537761703a20496e76616c69642041646472657373000000000000000000000060448201526064015b60405180910390fd5b620000fe888888886200062c565b6200014a6040518060400160405280601f81526020017f6f555344207377617020636f6e74726f6c6c6572206164647265737320257300815250846200078060201b6200138d1760201c565b60408051600280825260608201835260009260208301908036833701905050905084816000815181106200018e57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250508281600181518110620001d157634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392909216602092830291909101820152604080516002808252606082018352600093919290918301908036833701905050905084816000815181106200022f57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505083816001815181106200027257634e487b7160e01b600052603260045260246000fd5b6001600160a01b039290921660209283029190910182015260408051600280825260608201835260009391929091830190803683370190505090508381600081518110620002d057634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505084816001815181106200031357634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015262000338838383620007d1565b604080518082019091526001600160a01b03808716825288166020820152620003669060109060026200097c565b50604080518082019091526001600160a01b03808716825287166020820152620003959060119060026200097c565b50604080518082019091526001600160a01b03808716825285166020820152620003c49060129060026200097c565b50604080516001808252818301909252600091602080830190803683370190505090506000816000815181106200040b57634e487b7160e01b600052603260045260246000fd5b60ff92909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090506001816000815181106200046657634e487b7160e01b600052603260045260246000fd5b60ff90921660209283029190910190910152620004848282620008a3565b5050600980546001600160a01b03199081166001600160a01b03998a1617909155600a80548216978916979097179096555050600b8054851693861693909317909255600c80548416919094169081179093555060078054909116909117905550620012ea92505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146200058a5760405162461bcd60e51b81526020600482018190526024820152600080516020620056ef8339815191526044820152606401620000e7565b6001600160a01b038116620005e25760405162461bcd60e51b815260206004820152601760248201527f4f726375733a20496e76616c6964206f70657261746f720000000000000000006044820152606401620000e7565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fb3b3f5f64ab192e4b5fefde1f51ce9733bbdcf831951543b325aebd49cc27ec490600090a250565b6000546001600160a01b03163314620006775760405162461bcd60e51b81526020600482018190526024820152600080516020620056ef8339815191526044820152606401620000e7565b6001600160a01b03841615620006a357600380546001600160a01b0319166001600160a01b0386161790555b6001600160a01b03831615620006cf57600480546001600160a01b0319166001600160a01b0385161790555b6001600160a01b03821615620006fb57600580546001600160a01b0319166001600160a01b0384161790555b6001600160a01b038116156200072757600680546001600160a01b0319166001600160a01b0383161790555b604080516001600160a01b0386811682528581166020830152848116828401528316606082015290517fa48562da7f2be656ea6fb65809afa6b6c4507b30ea4494e55ae71ae7e2e6cce79181900360800190a150505050565b620007cd82826040516024016200079992919062001283565b60408051601f198184030181529190526020810180516001600160e01b0390811663319af33360e01b179091526200095b16565b5050565b6000546001600160a01b031633146200081c5760405162461bcd60e51b81526020600482018190526024820152600080516020620056ef8339815191526044820152606401620000e7565b82516200083190600d9060208601906200097c565b5081516200084790600e9060208501906200097c565b5080516200085d90600f9060208401906200097c565b507f515b59dedd2921ad3a8188614a7678c4ff22f32e451e12dd4695166d6b7f4b69600d600e600f604051620008969392919062001208565b60405180910390a1505050565b6000546001600160a01b03163314620008ee5760405162461bcd60e51b81526020600482018190526024820152600080516020620056ef8339815191526044820152606401620000e7565b815162000903906013906020850190620009e6565b50805162000919906014906020840190620009e6565b507f4830984616e187ffcfd6d1443460f0d9160c040ba32092da30482a0068c8579c601360146040516200094f92919062001251565b60405180910390a15050565b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b828054828255906000526020600020908101928215620009d4579160200282015b82811115620009d457825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906200099d565b50620009e292915062000a89565b5090565b82805482825590600052602060002090601f01602090048101928215620009d45791602002820160005b8382111562000a5057835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262000a10565b801562000a7f5782816101000a81549060ff021916905560010160208160000104928301926001030262000a50565b5050620009e29291505b5b80821115620009e2576000815560010162000a8a565b80516001600160a01b038116811462000ab857600080fd5b919050565b600080600080600080600080610100898b03121562000ada578384fd5b62000ae58962000aa0565b975062000af560208a0162000aa0565b965062000b0560408a0162000aa0565b955062000b1560608a0162000aa0565b945062000b2560808a0162000aa0565b935062000b3560a08a0162000aa0565b925062000b4560c08a0162000aa0565b915062000b5560e08a0162000aa0565b90509295985092959890939650565b6000815480845260208085019450838352808320835b8381101562000ba15781546001600160a01b03168752958201956001918201910162000b7a565b509495945050505050565b805480835260008281526020808220940193909190825b82601f8201101562000e6457815460ff8082168852602062000bee818a01838560081c1660ff169052565b604062000c04818b01848660101c1660ff169052565b606062000c1a818c01858760181c1660ff169052565b608062000c2f818d018688871c1660ff169052565b60a0935062000c47848d01868860281c1660ff169052565b60c062000c5d818e01878960301c1660ff169052565b60e062000c73818f01888a60381c1660ff169052565b60ff88861c8816166101008f015262000c976101208f01888a60481c1660ff169052565b62000cad6101408f01888a60501c1660ff169052565b62000cc36101608f01888a60581c1660ff169052565b60ff88851c8816166101808f015262000ce76101a08f01888a60681c1660ff169052565b62000cfd6101c08f01888a60701c1660ff169052565b62000d136101e08f01888a60781c1660ff169052565b60ff88841c8816166102008f015262000d376102208f01888a60881c1660ff169052565b62000d4d6102408f01888a60901c1660ff169052565b62000d636102608f01888a60981c1660ff169052565b60ff88871c8816166102808f015262000d876102a08f01888a60a81c1660ff169052565b62000d9d6102c08f01888a60b01c1660ff169052565b62000db36102e08f01888a60b81c1660ff169052565b60ff88831c8816166103008f015262000dd76103208f01888a60c81c1660ff169052565b62000ded6103408f01888a60d01c1660ff169052565b62000e036103608f01888a60d81c1660ff169052565b60ff88821c8816166103808f015250505050505062000e2d6103a08901828460e81c1660ff169052565b62000e436103c08901828460f01c1660ff169052565b5060f81c6103e0870152610400909501946001919091019060200162000bc3565b9054908281101562000e805760ff821686526020909501946001015b8281101562000e9d5760ff600883901c1686526020909501946001015b8281101562000eba5760ff601083901c1686526020909501946001015b8281101562000ed75760ff601883901c1686526020909501946001015b8281101562000ef557602082901c60ff168652602095909501946001015b8281101562000f125760ff602883901c1686526020909501946001015b8281101562000f2f5760ff603083901c1686526020909501946001015b8281101562000f4c5760ff603883901c1686526020909501946001015b8281101562000f695760ff604083901c1686526020909501946001015b8281101562000f865760ff604883901c1686526020909501946001015b8281101562000fa35760ff605083901c1686526020909501946001015b8281101562000fc05760ff605883901c1686526020909501946001015b8281101562000fdd5760ff606083901c1686526020909501946001015b8281101562000ffa5760ff606883901c1686526020909501946001015b82811015620010175760ff607083901c1686526020909501946001015b82811015620010345760ff607883901c1686526020909501946001015b82811015620010515760ff608083901c1686526020909501946001015b828110156200106e5760ff608883901c1686526020909501946001015b828110156200108b5760ff609083901c1686526020909501946001015b82811015620010a85760ff609883901c1686526020909501946001015b82811015620010c55760ff60a083901c1686526020909501946001015b82811015620010e25760ff60a883901c1686526020909501946001015b82811015620010ff5760ff60b083901c1686526020909501946001015b828110156200111c5760ff60b883901c1686526020909501946001015b82811015620011395760ff60c083901c1686526020909501946001015b82811015620011565760ff60c883901c1686526020909501946001015b82811015620011735760ff60d083901c1686526020909501946001015b82811015620011905760ff60d883901c1686526020909501946001015b82811015620011ad5760ff60e083901c1686526020909501946001015b82811015620011ca5760ff60e883901c1686526020909501946001015b82811015620011e75760ff60f083901c1686526020909501946001015b82811015620011fe5760f882901c86526020860195505b5093949350505050565b6060815260006200121d606083018662000b64565b828103602084015262001231818662000b64565b9050828103604084015262001247818562000b64565b9695505050505050565b60408152600062001266604083018562000bac565b82810360208401526200127a818562000bac565b95945050505050565b6040815260008351806040840152815b81811015620012b2576020818701810151606086840101520162001293565b81811115620012c45782606083860101525b506001600160a01b0393909316602083015250601f91909101601f191601606001919050565b6143f580620012fa6000396000f3fe608060405234801561001057600080fd5b50600436106101b05760003560e01c806388d7dfc0116100ef578063bebacc8e11610092578063bebacc8e14610394578063bf989b6e146103a7578063c493f6e0146103ba578063c7971475146103cd578063c7f79582146103e0578063e0243baa146103f3578063e2f2ee75146103fc578063f2fde38b1461040f57600080fd5b806388d7dfc0146103075780638d42b5561461031a5780638da5cb5b1461032d5780638dd95002146103355780639b11385614610348578063b3ab15fb1461035b578063b54d8f9f1461036e578063bb02b0511461038157600080fd5b806353cbaa461161015757806353cbaa461461026c57806355b88c271461028d578063570ca735146102a0578063681ba0bd146102b35780636d1e82fa146102c6578063715018a6146102d95780637157f95a146102e15780637a9ad7bf146102f457600080fd5b80630ab2a9a2146101b557806310adf9db146101e5578063145f6941146101f85780632bccfac91461020d57806333a397c3146102205780633462e8dd146102335780633883a6dd146102465780633e413bee14610259575b600080fd5b600c546101c8906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101c86101f33660046138a6565b610422565b61020b6102063660046136c0565b61044c565b005b61020b61021b3660046138d6565b610503565b6101c861022e3660046138a6565b6105fa565b6101c86102413660046138a6565b61060a565b6003546101c8906001600160a01b031681565b600b546101c8906001600160a01b031681565b61027f61027a36600461391a565b61061a565b6040519081526020016101dc565b61020b61029b3660046138d6565b610842565b6002546101c8906001600160a01b031681565b6009546101c8906001600160a01b031681565b6101c86102d43660046138a6565b61090b565b61020b61091b565b61020b6102ef3660046138d6565b610956565b6005546101c8906001600160a01b031681565b61027f61031536600461391a565b6109f3565b61027f6103283660046138d6565b610b04565b6101c8610c8e565b6007546101c8906001600160a01b031681565b6006546101c8906001600160a01b031681565b61020b61036936600461362d565b610c9d565b6004546101c8906001600160a01b031681565b61020b61038f3660046138d6565b610d66565b600a546101c8906001600160a01b031681565b61020b6103b5366004613665565b610e03565b61020b6103c83660046137d7565b610f37565b6101c86103db3660046138a6565b610fcd565b61020b6103ee3660046138d6565b610fdd565b61027f60085481565b6101c861040a3660046138a6565b6112dd565b61020b61041d36600461362d565b6112ed565b600e818154811061043257600080fd5b6000918252602090912001546001600160a01b0316905081565b33610455610c8e565b6001600160a01b0316146104845760405162461bcd60e51b815260040161047b906141c8565b60405180910390fd5b825161049790600d90602086019061341c565b5081516104ab90600e90602085019061341c565b5080516104bf90600f90602084019061341c565b507f515b59dedd2921ad3a8188614a7678c4ff22f32e451e12dd4695166d6b7f4b69600d600e600f6040516104f693929190614097565b60405180910390a1505050565b600260015414156105265760405162461bcd60e51b815260040161047b906141fd565b6002600155600c54610543906001600160a01b03163330856113d6565b600354600c54610561916001600160a01b0391821691166000611434565b600354600c5461057e916001600160a01b03918216911684611434565b6003546001600160a01b0316635c11d7958383600f336105a061012c426142e4565b6040518663ffffffff1660e01b81526004016105c0959493929190614270565b600060405180830381600087803b1580156105da57600080fd5b505af11580156105ee573d6000803e3d6000fd5b50506001805550505050565b600f818154811061043257600080fd5b6012818154811061043257600080fd5b60006002600154141561063f5760405162461bcd60e51b815260040161047b906141fd565b600260015560095461065c906001600160a01b03163330876113d6565b604080516003808252608082019092526000916020820160608036833701905050905084816000815181106106a157634e487b7160e01b600052603260045260246000fd5b60200260200101818152505083816001815181106106cf57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505082816002815181106106fd57634e487b7160e01b600052603260045260246000fd5b602090810291909101015260095460055460009161072b916001600160a01b0391821691859116600161154c565b90506000811161076b5760405162461bcd60e51b815260206004820152600b60248201526a0537761703a204e6f206c760ac1b604482015260640161047b565b60055460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061079d903390859060040161407e565b602060405180830381600087803b1580156107b757600080fd5b505af11580156107cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ef9190613838565b6108355760405162461bcd60e51b815260206004820152601760248201527629bbb0b81d102330b4b632103a37903a3930b739b332b960491b604482015260640161047b565b6001805595945050505050565b600260015414156108655760405162461bcd60e51b815260040161047b906141fd565b6002600155600954610882906001600160a01b03163330856113d6565b6003546009546108a0916001600160a01b0391821691166000611434565b6003546009546108bd916001600160a01b03918216911684611434565b6108e96040518060400160405280600b81526020016a777466207765206865726560a81b815250611926565b6003546001600160a01b0316635c11d7958383600d336105a061012c426142e4565b6010818154811061043257600080fd5b33610924610c8e565b6001600160a01b03161461094a5760405162461bcd60e51b815260040161047b906141c8565b6109546000611969565b565b600260015414156109795760405162461bcd60e51b815260040161047b906141fd565b6002600155600b54610996906001600160a01b03163330856113d6565b600354600b546109b4916001600160a01b0391821691166000611434565b600354600b546109d1916001600160a01b03918216911684611434565b6003546001600160a01b0316635c11d79583836010336105a061012c426142e4565b600060026001541415610a185760405162461bcd60e51b815260040161047b906141fd565b6002600155600b54610a35906001600160a01b03163330876113d6565b60408051600380825260808201909252600091602082016060803683370190505090508481600081518110610a7a57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508381600181518110610aa857634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508281600281518110610ad657634e487b7160e01b600052603260045260246000fd5b6020908102919091010152600b5460055460009161072b916001600160a01b0391821691859116600161154c565b600060026001541415610b295760405162461bcd60e51b815260040161047b906141fd565b60026001556005546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90610b629033903090889060040161405a565b602060405180830381600087803b158015610b7c57600080fd5b505af1158015610b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb49190613838565b610c005760405162461bcd60e51b815260206004820152601d60248201527f537761703a204661696c656420746f207472616e736665722070616972000000604482015260640161047b565b600554600954600091610c22916001600160a01b0391821691879116866119b9565b905060008111610c6c5760405162461bcd60e51b81526020600482015260156024820152740537761703a204f727520616d6f756e74206973203605c1b604482015260640161047b565b600954610c83906001600160a01b03163383611cef565b600180559392505050565b6000546001600160a01b031690565b33610ca6610c8e565b6001600160a01b031614610ccc5760405162461bcd60e51b815260040161047b906141c8565b6001600160a01b038116610d1c5760405162461bcd60e51b815260206004820152601760248201527627b931bab99d1024b73b30b634b21037b832b930ba37b960491b604482015260640161047b565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fb3b3f5f64ab192e4b5fefde1f51ce9733bbdcf831951543b325aebd49cc27ec490600090a250565b60026001541415610d895760405162461bcd60e51b815260040161047b906141fd565b6002600155600a54610da6906001600160a01b03163330856113d6565b600354600a54610dc4916001600160a01b0391821691166000611434565b600354600a54610de1916001600160a01b03918216911684611434565b6003546001600160a01b0316635c11d7958383600e336105a061012c426142e4565b33610e0c610c8e565b6001600160a01b031614610e325760405162461bcd60e51b815260040161047b906141c8565b6001600160a01b03841615610e5d57600380546001600160a01b0319166001600160a01b0386161790555b6001600160a01b03831615610e8857600480546001600160a01b0319166001600160a01b0385161790555b6001600160a01b03821615610eb357600580546001600160a01b0319166001600160a01b0384161790555b6001600160a01b03811615610ede57600680546001600160a01b0319166001600160a01b0383161790555b604080516001600160a01b0386811682528581166020830152848116828401528316606082015290517fa48562da7f2be656ea6fb65809afa6b6c4507b30ea4494e55ae71ae7e2e6cce79181900360800190a150505050565b33610f40610c8e565b6001600160a01b031614610f665760405162461bcd60e51b815260040161047b906141c8565b8151610f79906013906020850190613481565b508051610f8d906014906020840190613481565b507f4830984616e187ffcfd6d1443460f0d9160c040ba32092da30482a0068c8579c60136014604051610fc19291906140da565b60405180910390a15050565b6011818154811061043257600080fd5b600260015414156110005760405162461bcd60e51b815260040161047b906141fd565b6002600155600b5461101d906001600160a01b03163330856113d6565b600354600b5461103b916001600160a01b0391821691166000611434565b600354600b54611058916001600160a01b03918216911684611434565b600b546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561109c57600080fd5b505afa1580156110b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d491906138be565b90506110fd6040518060400160405280600681526020016534206865726560d01b815250611926565b61113c6040518060400160405280601f81526020017f7377617020636f6e74726f6c6c657220757364632062616c616e63652025730081525082611d0e565b6000806000600660009054906101000a90046001600160a01b03166001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561118f57600080fd5b505afa1580156111a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c79190613858565b9250925092506112156040518060400160405280601c81526020017f52657365727665732061667465722063616c6c6261636b203020257300000000815250846001600160701b0316611d0e565b61125d6040518060400160405280601c81526020017f52657365727665732061667465722063616c6c6261636b203120257300000000815250836001600160701b0316611d0e565b6003546001600160a01b0316635c11d795878760113361127f61012c426142e4565b6040518663ffffffff1660e01b815260040161129f959493929190614270565b600060405180830381600087803b1580156112b957600080fd5b505af11580156112cd573d6000803e3d6000fd5b5050600180555050505050505050565b600d818154811061043257600080fd5b336112f6610c8e565b6001600160a01b03161461131c5760405162461bcd60e51b815260040161047b906141c8565b6001600160a01b0381166113815760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161047b565b61138a81611969565b50565b6113d282826040516024016113a3929190614147565b60408051601f198184030181529190526020810180516001600160e01b031663319af33360e01b179052611d4f565b5050565b61142e846323b872dd60e01b8585856040516024016113f79392919061405a565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611d70565b50505050565b8015806114bd5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561148357600080fd5b505afa158015611497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bb91906138be565b155b6115285760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161047b565b6115478363095ea7b360e01b84846040516024016113f792919061407e565b505050565b600061155785611e42565b826001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561159057600080fd5b505afa1580156115a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c89190613649565b6001600160a01b0316856001600160a01b031614806116685750826001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561161b57600080fd5b505afa15801561162f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116539190613649565b6001600160a01b0316856001600160a01b0316145b15611863576000806000856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156116ab57600080fd5b505afa1580156116bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e39190613649565b90506000866001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561172057600080fd5b505afa158015611734573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117589190613649565b9050816001600160a01b0316896001600160a01b031614611779578161177b565b805b93506117b1878a8a6000815181106117a357634e487b7160e01b600052603260045260246000fd5b602002602001015185611ee5565b9250505060006117c4888385308a611fca565b9050866001815181106117e757634e487b7160e01b600052603260045260246000fd5b602002602001015181101561180e5760405162461bcd60e51b815260040161047b90614193565b61185986898561184f868c60008151811061183957634e487b7160e01b600052603260045260246000fd5b602002602001015161226a90919063ffffffff16565b853060008c6122c6565b93505050506118ae565b600061189a868660008151811061188a57634e487b7160e01b600052603260045260246000fd5b6020026020010151306000612438565b90506118aa8482306000876126c9565b9150505b836002815181106118cf57634e487b7160e01b600052603260045260246000fd5b602002602001015181101561191e5760405162461bcd60e51b81526020600482015260156024820152742d30b81d102434b3b41029b634b83830b3b29024b760591b604482015260640161047b565b949350505050565b61138a8160405160240161193a9190614134565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b179052611d4f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006119c485611e42565b6000806000806000899050806001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611a0857600080fd5b505afa158015611a1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a409190613649565b9450806001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015611a7b57600080fd5b505afa158015611a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab39190613649565b600354604051635d5155ef60e11b81526001600160a01b0388811660048301528084166024830152604482018d905260006064830181905260848301523060a48301524260c483015292965091169063baa2abde9060e4016040805180830381600087803b158015611b2457600080fd5b505af1158015611b38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5c91906138f7565b909350915060009050611b6e85611e42565b611b7784611e42565b6007546001600160a01b0389811691161415611bf4576007546000906001600160a01b0387811691161480611bb957506007546001600160a01b038681169116145b611bc4576000611bc6565b8a5b9050611bd486853084612438565b9150611be285843084612438565b611bec90836142e4565b915050611c60565b6000856001600160a01b0316896001600160a01b03161480611c275750846001600160a01b0316896001600160a01b0316145b611c32576000611c34565b8a5b9050611c4386858b3085611fca565b9150611c5285848b3085611fca565b611c5c90836142e4565b9150505b86811015611ca95760405162461bcd60e51b815260206004820152601660248201527516985c0e88121a59da0814db1a5c1c1859d94813dd5d60521b604482015260640161047b565b6007546001600160a01b0389811691161415611cce57611cc93082612c39565b611ce2565b611ce26001600160a01b0389163083611cef565b9998505050505050505050565b6115478363a9059cbb60e01b84846040516024016113f792919061407e565b6113d28282604051602401611d24929190614171565b60408051601f198184030181529190526020810180516001600160e01b03166309710a9d60e41b1790525b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b6000611dc5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d139092919063ffffffff16565b8051909150156115475780806020019051810190611de39190613838565b6115475760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161047b565b600354604051636eb1769f60e11b81523060048201526001600160a01b0391821660248201529082169063dd62ed3e9060440160206040518083038186803b158015611e8d57600080fd5b505afa158015611ea1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec591906138be565b61138a5760035461138a906001600160a01b038381169116600019611434565b600060328082600080896001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015611f2757600080fd5b505afa158015611f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5f9190613858565b506001600160701b031691506001600160701b031691506000876001600160a01b03168a6001600160a01b031614611f975781611f99565b825b90506000611fa96127108661226a565b9050611fb6828b83612d2c565b97505050505050505061191e565b90612e20565b6000836001600160a01b0316866001600160a01b03161415612011576001600160a01b038316301461200a5761200a6001600160a01b0387168487611cef565b5083612261565b604080516002808252606082018352600092602083019080368337019050509050868160008151811061205457634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050848160018151811061209657634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280516060901561214e576003546040516338ed173960e01b81526001600160a01b03909116906338ed1739906120f1908a9060019087908b904290600401614234565b600060405180830381600087803b15801561210b57600080fd5b505af115801561211f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526121479190810190613744565b9050612227565b6001600160a01b038416156121e5576040805160018082528183019092529060208083019080368337019050509150838260008151811061219f57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526003546040516338ed173960e01b81529116906338ed1739906120f1908a9060019087908b904290600401614234565b60405162461bcd60e51b8152602060048201526017602482015276046697265426972645a61703a202170617468207377617604c1b604482015260640161047b565b8060018251612236919061433b565b8151811061225457634e487b7160e01b600052603260045260246000fd5b6020026020010151925050505b95945050505050565b600082612277838261433b565b91508111156122c05760405162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b604482015260640161047b565b92915050565b60006122d188611e42565b6122da87611e42565b60035460405162e8e33760e81b81526001600160a01b038a811660048301528981166024830152604482018990526064820188905260016084830181905260a483015286811660c48301524260e4830152600092839291169063e8e337009061010401606060405180830381600087803b15801561235757600080fd5b505af115801561236b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238f9190613945565b9450909250905060006123a2898461226a565b905084806123c957506123c6612710611fc46008548c612db990919063ffffffff16565b81115b156123df5780156123df576123df8b3383612e76565b60006123eb898461226a565b90508580612412575061240f612710611fc46008548c612db990919063ffffffff16565b81115b15612428578015612428576124288b3383612e76565b5050505098975050505050505050565b6007546000906001600160a01b038681169116141561246f57600754612468906001600160a01b03168486612e76565b508261191e565b60408051600280825260608201835260009260208301908036833701905050905085816000815181106124b257634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526007548251911690829060019081106124f157634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528051606090156125a9576003546040516318cbafe560e01b81526001600160a01b03909116906318cbafe59061254c90899060019087908b904290600401614234565b600060405180830381600087803b15801561256657600080fd5b505af115801561257a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526125a29190810190613744565b9050612688565b6001600160a01b0384161561264057604080516001808252818301909252906020808301908036833701905050915083826000815181106125fa57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526003546040516318cbafe560e01b81529116906318cbafe59061254c90899060019087908b904290600401614234565b60405162461bcd60e51b815260206004820152601b60248201527f46697265426972645a61703a20217061746820546f6b656e424e420000000000604482015260640161047b565b8060018251612697919061433b565b815181106126b557634e487b7160e01b600052603260045260246000fd5b602002602001015192505050949350505050565b600080869050600760009054906101000a90046001600160a01b03166001600160a01b0316876001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561272757600080fd5b505afa15801561273b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275f9190613649565b6001600160a01b031614806127f957506007546040805163d21220a760e01b815290516001600160a01b03928316928a169163d21220a7916004808301926020929190829003018186803b1580156127b657600080fd5b505afa1580156127ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ee9190613649565b6001600160a01b0316145b15612aed576000600760009054906101000a90046001600160a01b03166001600160a01b0316886001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561285857600080fd5b505afa15801561286c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128909190613649565b6001600160a01b03161461291457876001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156128d757600080fd5b505afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290f9190613649565b612985565b876001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561294d57600080fd5b505afa158015612961573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129859190613649565b90506000612a1a83600760009054906101000a90046001600160a01b03168a8c6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156129dd57600080fd5b505afa1580156129f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a159190613649565b611ee5565b90506000612a2a83833087612f22565b905086811015612a4c5760405162461bcd60e51b815260040161047b90614193565b6000612a588a8461226a565b9050600760009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612aaa57600080fd5b505af1158015612abe573d6000803e3d6000fd5b5050600754612ae293508892506001600160a01b031690508684868e60008e6122c6565b955050505050612c2f565b6000876001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015612b2857600080fd5b505afa158015612b3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b609190613649565b90506000886001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015612b9d57600080fd5b505afa158015612bb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd59190613649565b9050600080603281612bec6064611fc48e85612db9565b9050612bfb8682306000612f22565b9350612c1385612c0b8e8461226a565b306000612f22565b92505050612c2885858585858e60008e6122c6565b9550505050505b5095945050505050565b604080516000808252602082019092526001600160a01b038416908390604051612c63919061403e565b60006040518083038185875af1925050503d8060008114612ca0576040519150601f19603f3d011682016040523d82523d6000602084013e612ca5565b606091505b50509050806115475760405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527308115512081d1c985b9cd9995c8819985a5b195960621b606482015260840161047b565b6060612d2284846000856131ed565b90505b9392505050565b6000612d39826002612db9565b612daf612d52612d4b8561271061331e565b8790612db9565b612da9612da4612d83612d678861271061331e565b612d7d612d768a61271061331e565b8c90612db9565b90612db9565b612d9388612d7d8b619c40612db9565b612d9d91906142e4565b8990612db9565b613373565b9061226a565b612d2291906142fc565b6000811580612ddd57508282612dcf818361431c565b9250612ddb90836142fc565b145b6122c05760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604482015260640161047b565b6000808211612e6c5760405162461bcd60e51b815260206004820152601860248201527764732d6d6174682d6469766973696f6e2d62792d7a65726f60401b604482015260640161047b565b612d2582846142fc565b80612e8057505050565b6007546001600160a01b0384811691161415612f0e57600754604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b158015612edc57600080fd5b505af1158015612ef0573d6000803e3d6000fd5b505050506001600160a01b0382163014611547576115478282612c39565b6115476001600160a01b0384168383611cef565b6007546000906001600160a01b0386811691161415612fcc57600760009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f8b57600080fd5b505af1158015612f9f573d6000803e3d6000fd5b505050506001600160a01b0384163014905061246857600754612468906001600160a01b03168486611cef565b604080516002808252606082018352600092602083019080368337505060075482519293506001600160a01b03169183915060009061301b57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050858160018151811061305d57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280516060901561310e57600354604051637ff36ab560e01b81526001600160a01b0390911690637ff36ab59088906130b89060019087908b9042906004016140ff565b6000604051808303818588803b1580156130d157600080fd5b505af11580156130e5573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526125a29190810190613744565b6001600160a01b038416156131a5576040805160018082528183019092529060208083019080368337019050509150838260008151811061315f57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152600354604051637ff36ab560e01b8152911690637ff36ab59088906130b89060019087908b9042906004016140ff565b60405162461bcd60e51b815260206004820152601b60248201527f46697265426972645a61703a20217061746820424e42546f6b656e0000000000604482015260640161047b565b60608247101561324e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161047b565b6001600160a01b0385163b6132a55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161047b565b600080866001600160a01b031685876040516132c1919061403e565b60006040518083038185875af1925050503d80600081146132fe576040519150601f19603f3d011682016040523d82523d6000602084013e613303565b606091505b50915091506133138282866133e3565b979650505050505050565b60008261332b83826142e4565b91508110156122c05760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b604482015260640161047b565b600060038211156133d4575080600061338d6002836142fc565b6133989060016142e4565b90505b818110156133ce579050806002816133b381866142fc565b6133bd91906142e4565b6133c791906142fc565b905061339b565b50919050565b81156133de575060015b919050565b606083156133f2575081612d25565b8251156134025782518084602001fd5b8160405162461bcd60e51b815260040161047b9190614134565b828054828255906000526020600020908101928215613471579160200282015b8281111561347157825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061343c565b5061347d92915061351e565b5090565b82805482825590600052602060002090601f016020900481019282156134715791602002820160005b838211156134e857835183826101000a81548160ff021916908360ff16021790555092602001926001016020816000010492830192600103026134aa565b80156135155782816101000a81549060ff02191690556001016020816000010492830192600103026134e8565b505061347d9291505b5b8082111561347d576000815560010161351f565b600082601f830112613543578081fd5b81356020613558613553836142c0565b61428f565b80838252828201915082860187848660051b8901011115613577578586fd5b855b8581101561359e57813561358c816143aa565b84529284019290840190600101613579565b5090979650505050505050565b600082601f8301126135bb578081fd5b813560206135cb613553836142c0565b80838252828201915082860187848660051b89010111156135ea578586fd5b855b8581101561359e57813560ff81168114613604578788fd5b845292840192908401906001016135ec565b80516001600160701b03811681146133de57600080fd5b60006020828403121561363e578081fd5b8135612d25816143aa565b60006020828403121561365a578081fd5b8151612d25816143aa565b6000806000806080858703121561367a578283fd5b8435613685816143aa565b93506020850135613695816143aa565b925060408501356136a5816143aa565b915060608501356136b5816143aa565b939692955090935050565b6000806000606084860312156136d4578283fd5b833567ffffffffffffffff808211156136eb578485fd5b6136f787838801613533565b9450602086013591508082111561370c578384fd5b61371887838801613533565b9350604086013591508082111561372d578283fd5b5061373a86828701613533565b9150509250925092565b60006020808385031215613756578182fd5b825167ffffffffffffffff81111561376c578283fd5b8301601f8101851361377c578283fd5b805161378a613553826142c0565b80828252848201915084840188868560051b87010111156137a9578687fd5b8694505b838510156137cb5780518352600194909401939185019185016137ad565b50979650505050505050565b600080604083850312156137e9578182fd5b823567ffffffffffffffff80821115613800578384fd5b61380c868387016135ab565b93506020850135915080821115613821578283fd5b5061382e858286016135ab565b9150509250929050565b600060208284031215613849578081fd5b81518015158114612d25578182fd5b60008060006060848603121561386c578283fd5b61387584613616565b925061388360208501613616565b9150604084015163ffffffff8116811461389b578182fd5b809150509250925092565b6000602082840312156138b7578081fd5b5035919050565b6000602082840312156138cf578081fd5b5051919050565b600080604083850312156138e8578182fd5b50508035926020909101359150565b60008060408385031215613909578182fd5b505080516020909101519092909150565b60008060006060848603121561392e578081fd5b505081359360208301359350604090920135919050565b600080600060608486031215613959578081fd5b8351925060208401519150604084015190509250925092565b6000815180845260208085019450808401835b838110156139aa5781516001600160a01b031687529582019590820190600101613985565b509495945050505050565b6000815480845260208085019450838352808320835b838110156139aa5781546001600160a01b0316875295820195600191820191016139cb565b805480835260008281526020808220940193909190825b82601f82011015613c8e57815460ff80821688526020613a30818a01838560081c1660ff169052565b6040613a45818b01848660101c1660ff169052565b6060613a5a818c01858760181c1660ff169052565b6080613a6e818d018688871c1660ff169052565b60a09350613a85848d01868860281c1660ff169052565b60c0613a9a818e01878960301c1660ff169052565b60e0613aaf818f01888a60381c1660ff169052565b60ff88861c8816166101008f0152613ad26101208f01888a60481c1660ff169052565b613ae76101408f01888a60501c1660ff169052565b613afc6101608f01888a60581c1660ff169052565b60ff88851c8816166101808f0152613b1f6101a08f01888a60681c1660ff169052565b613b346101c08f01888a60701c1660ff169052565b613b496101e08f01888a60781c1660ff169052565b60ff88841c8816166102008f0152613b6c6102208f01888a60881c1660ff169052565b613b816102408f01888a60901c1660ff169052565b613b966102608f01888a60981c1660ff169052565b60ff88871c8816166102808f0152613bb96102a08f01888a60a81c1660ff169052565b613bce6102c08f01888a60b01c1660ff169052565b613be36102e08f01888a60b81c1660ff169052565b60ff88831c8816166103008f0152613c066103208f01888a60c81c1660ff169052565b613c1b6103408f01888a60d01c1660ff169052565b613c306103608f01888a60d81c1660ff169052565b60ff88821c8816166103808f0152505050505050613c596103a08901828460e81c1660ff169052565b613c6e6103c08901828460f01c1660ff169052565b5060f81c6103e08701526104009095019460019190910190602001613a07565b90549082811015613ca95760ff821686526020909501946001015b82811015613cc55760ff600883901c1686526020909501946001015b82811015613ce15760ff601083901c1686526020909501946001015b82811015613cfd5760ff601883901c1686526020909501946001015b82811015613d1a57602082901c60ff168652602095909501946001015b82811015613d365760ff602883901c1686526020909501946001015b82811015613d525760ff603083901c1686526020909501946001015b82811015613d6e5760ff603883901c1686526020909501946001015b82811015613d8a5760ff604083901c1686526020909501946001015b82811015613da65760ff604883901c1686526020909501946001015b82811015613dc25760ff605083901c1686526020909501946001015b82811015613dde5760ff605883901c1686526020909501946001015b82811015613dfa5760ff606083901c1686526020909501946001015b82811015613e165760ff606883901c1686526020909501946001015b82811015613e325760ff607083901c1686526020909501946001015b82811015613e4e5760ff607883901c1686526020909501946001015b82811015613e6a5760ff608083901c1686526020909501946001015b82811015613e865760ff608883901c1686526020909501946001015b82811015613ea25760ff609083901c1686526020909501946001015b82811015613ebe5760ff609883901c1686526020909501946001015b82811015613eda5760ff60a083901c1686526020909501946001015b82811015613ef65760ff60a883901c1686526020909501946001015b82811015613f125760ff60b083901c1686526020909501946001015b82811015613f2e5760ff60b883901c1686526020909501946001015b82811015613f4a5760ff60c083901c1686526020909501946001015b82811015613f665760ff60c883901c1686526020909501946001015b82811015613f825760ff60d083901c1686526020909501946001015b82811015613f9e5760ff60d883901c1686526020909501946001015b82811015613fba5760ff60e083901c1686526020909501946001015b82811015613fd65760ff60e883901c1686526020909501946001015b82811015613ff25760ff60f083901c1686526020909501946001015b828110156140085760f882901c86526020860195505b5093949350505050565b6000815180845261402a816020860160208601614352565b601f01601f19169290920160200192915050565b60008251614050818460208701614352565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6060815260006140aa60608301866139b5565b82810360208401526140bc81866139b5565b905082810360408401526140d081856139b5565b9695505050505050565b6040815260006140ed60408301856139f0565b828103602084015261226181856139f0565b8481526080602082015260006141186080830186613972565b6001600160a01b03949094166040830152506060015292915050565b602081526000612d256020830184614012565b60408152600061415a6040830185614012565b905060018060a01b03831660208301529392505050565b6040815260006141846040830185614012565b90508260208301529392505050565b6020808252818101527f5a61703a20496e73756666696369656e74205265636569766520416d6f756e74604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b85815284602082015260a06040820152600061425360a0830186613972565b6001600160a01b0394909416606083015250608001529392505050565b85815284602082015260a06040820152600061425360a08301866139b5565b604051601f8201601f1916810167ffffffffffffffff811182821017156142b8576142b8614394565b604052919050565b600067ffffffffffffffff8211156142da576142da614394565b5060051b60200190565b600082198211156142f7576142f761437e565b500190565b60008261431757634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156143365761433661437e565b500290565b60008282101561434d5761434d61437e565b500390565b60005b8381101561436d578181015183820152602001614355565b8381111561142e5750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461138a57600080fdfea264697066735822122095d52a71b04e6318103606eb49e3eed4a30f8c91450ae09b2c8d7c6117bbf44364736f6c634300080400334f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572000000000000000000000000e915d2393a08a00c5a463053edd31bae2199b9e7000000000000000000000000a9473608514457b4bf083f9045fa63ae5810a03e00000000000000000000000043783ece7b46bb026d4cebfd3e29f539ff1914fb000000000000000000000000cf83a3d83c1265780d9374e8a7c838fe22bd3dc6000000000000000000000000cdb32eed99aa19d39e5d6ec45ba74dc4afec549f00000000000000000000000029f6e49c6e3397c3a84f715885f9f233a441165c0000000000000000000000006a2d262d56735dba19dd70682b39f6be9a931d98000000000000000000000000aeaaf0e2c81af264101b9129c00f4440ccf0f720

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101b05760003560e01c806388d7dfc0116100ef578063bebacc8e11610092578063bebacc8e14610394578063bf989b6e146103a7578063c493f6e0146103ba578063c7971475146103cd578063c7f79582146103e0578063e0243baa146103f3578063e2f2ee75146103fc578063f2fde38b1461040f57600080fd5b806388d7dfc0146103075780638d42b5561461031a5780638da5cb5b1461032d5780638dd95002146103355780639b11385614610348578063b3ab15fb1461035b578063b54d8f9f1461036e578063bb02b0511461038157600080fd5b806353cbaa461161015757806353cbaa461461026c57806355b88c271461028d578063570ca735146102a0578063681ba0bd146102b35780636d1e82fa146102c6578063715018a6146102d95780637157f95a146102e15780637a9ad7bf146102f457600080fd5b80630ab2a9a2146101b557806310adf9db146101e5578063145f6941146101f85780632bccfac91461020d57806333a397c3146102205780633462e8dd146102335780633883a6dd146102465780633e413bee14610259575b600080fd5b600c546101c8906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101c86101f33660046138a6565b610422565b61020b6102063660046136c0565b61044c565b005b61020b61021b3660046138d6565b610503565b6101c861022e3660046138a6565b6105fa565b6101c86102413660046138a6565b61060a565b6003546101c8906001600160a01b031681565b600b546101c8906001600160a01b031681565b61027f61027a36600461391a565b61061a565b6040519081526020016101dc565b61020b61029b3660046138d6565b610842565b6002546101c8906001600160a01b031681565b6009546101c8906001600160a01b031681565b6101c86102d43660046138a6565b61090b565b61020b61091b565b61020b6102ef3660046138d6565b610956565b6005546101c8906001600160a01b031681565b61027f61031536600461391a565b6109f3565b61027f6103283660046138d6565b610b04565b6101c8610c8e565b6007546101c8906001600160a01b031681565b6006546101c8906001600160a01b031681565b61020b61036936600461362d565b610c9d565b6004546101c8906001600160a01b031681565b61020b61038f3660046138d6565b610d66565b600a546101c8906001600160a01b031681565b61020b6103b5366004613665565b610e03565b61020b6103c83660046137d7565b610f37565b6101c86103db3660046138a6565b610fcd565b61020b6103ee3660046138d6565b610fdd565b61027f60085481565b6101c861040a3660046138a6565b6112dd565b61020b61041d36600461362d565b6112ed565b600e818154811061043257600080fd5b6000918252602090912001546001600160a01b0316905081565b33610455610c8e565b6001600160a01b0316146104845760405162461bcd60e51b815260040161047b906141c8565b60405180910390fd5b825161049790600d90602086019061341c565b5081516104ab90600e90602085019061341c565b5080516104bf90600f90602084019061341c565b507f515b59dedd2921ad3a8188614a7678c4ff22f32e451e12dd4695166d6b7f4b69600d600e600f6040516104f693929190614097565b60405180910390a1505050565b600260015414156105265760405162461bcd60e51b815260040161047b906141fd565b6002600155600c54610543906001600160a01b03163330856113d6565b600354600c54610561916001600160a01b0391821691166000611434565b600354600c5461057e916001600160a01b03918216911684611434565b6003546001600160a01b0316635c11d7958383600f336105a061012c426142e4565b6040518663ffffffff1660e01b81526004016105c0959493929190614270565b600060405180830381600087803b1580156105da57600080fd5b505af11580156105ee573d6000803e3d6000fd5b50506001805550505050565b600f818154811061043257600080fd5b6012818154811061043257600080fd5b60006002600154141561063f5760405162461bcd60e51b815260040161047b906141fd565b600260015560095461065c906001600160a01b03163330876113d6565b604080516003808252608082019092526000916020820160608036833701905050905084816000815181106106a157634e487b7160e01b600052603260045260246000fd5b60200260200101818152505083816001815181106106cf57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505082816002815181106106fd57634e487b7160e01b600052603260045260246000fd5b602090810291909101015260095460055460009161072b916001600160a01b0391821691859116600161154c565b90506000811161076b5760405162461bcd60e51b815260206004820152600b60248201526a0537761703a204e6f206c760ac1b604482015260640161047b565b60055460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061079d903390859060040161407e565b602060405180830381600087803b1580156107b757600080fd5b505af11580156107cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ef9190613838565b6108355760405162461bcd60e51b815260206004820152601760248201527629bbb0b81d102330b4b632103a37903a3930b739b332b960491b604482015260640161047b565b6001805595945050505050565b600260015414156108655760405162461bcd60e51b815260040161047b906141fd565b6002600155600954610882906001600160a01b03163330856113d6565b6003546009546108a0916001600160a01b0391821691166000611434565b6003546009546108bd916001600160a01b03918216911684611434565b6108e96040518060400160405280600b81526020016a777466207765206865726560a81b815250611926565b6003546001600160a01b0316635c11d7958383600d336105a061012c426142e4565b6010818154811061043257600080fd5b33610924610c8e565b6001600160a01b03161461094a5760405162461bcd60e51b815260040161047b906141c8565b6109546000611969565b565b600260015414156109795760405162461bcd60e51b815260040161047b906141fd565b6002600155600b54610996906001600160a01b03163330856113d6565b600354600b546109b4916001600160a01b0391821691166000611434565b600354600b546109d1916001600160a01b03918216911684611434565b6003546001600160a01b0316635c11d79583836010336105a061012c426142e4565b600060026001541415610a185760405162461bcd60e51b815260040161047b906141fd565b6002600155600b54610a35906001600160a01b03163330876113d6565b60408051600380825260808201909252600091602082016060803683370190505090508481600081518110610a7a57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508381600181518110610aa857634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508281600281518110610ad657634e487b7160e01b600052603260045260246000fd5b6020908102919091010152600b5460055460009161072b916001600160a01b0391821691859116600161154c565b600060026001541415610b295760405162461bcd60e51b815260040161047b906141fd565b60026001556005546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90610b629033903090889060040161405a565b602060405180830381600087803b158015610b7c57600080fd5b505af1158015610b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb49190613838565b610c005760405162461bcd60e51b815260206004820152601d60248201527f537761703a204661696c656420746f207472616e736665722070616972000000604482015260640161047b565b600554600954600091610c22916001600160a01b0391821691879116866119b9565b905060008111610c6c5760405162461bcd60e51b81526020600482015260156024820152740537761703a204f727520616d6f756e74206973203605c1b604482015260640161047b565b600954610c83906001600160a01b03163383611cef565b600180559392505050565b6000546001600160a01b031690565b33610ca6610c8e565b6001600160a01b031614610ccc5760405162461bcd60e51b815260040161047b906141c8565b6001600160a01b038116610d1c5760405162461bcd60e51b815260206004820152601760248201527627b931bab99d1024b73b30b634b21037b832b930ba37b960491b604482015260640161047b565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fb3b3f5f64ab192e4b5fefde1f51ce9733bbdcf831951543b325aebd49cc27ec490600090a250565b60026001541415610d895760405162461bcd60e51b815260040161047b906141fd565b6002600155600a54610da6906001600160a01b03163330856113d6565b600354600a54610dc4916001600160a01b0391821691166000611434565b600354600a54610de1916001600160a01b03918216911684611434565b6003546001600160a01b0316635c11d7958383600e336105a061012c426142e4565b33610e0c610c8e565b6001600160a01b031614610e325760405162461bcd60e51b815260040161047b906141c8565b6001600160a01b03841615610e5d57600380546001600160a01b0319166001600160a01b0386161790555b6001600160a01b03831615610e8857600480546001600160a01b0319166001600160a01b0385161790555b6001600160a01b03821615610eb357600580546001600160a01b0319166001600160a01b0384161790555b6001600160a01b03811615610ede57600680546001600160a01b0319166001600160a01b0383161790555b604080516001600160a01b0386811682528581166020830152848116828401528316606082015290517fa48562da7f2be656ea6fb65809afa6b6c4507b30ea4494e55ae71ae7e2e6cce79181900360800190a150505050565b33610f40610c8e565b6001600160a01b031614610f665760405162461bcd60e51b815260040161047b906141c8565b8151610f79906013906020850190613481565b508051610f8d906014906020840190613481565b507f4830984616e187ffcfd6d1443460f0d9160c040ba32092da30482a0068c8579c60136014604051610fc19291906140da565b60405180910390a15050565b6011818154811061043257600080fd5b600260015414156110005760405162461bcd60e51b815260040161047b906141fd565b6002600155600b5461101d906001600160a01b03163330856113d6565b600354600b5461103b916001600160a01b0391821691166000611434565b600354600b54611058916001600160a01b03918216911684611434565b600b546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561109c57600080fd5b505afa1580156110b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d491906138be565b90506110fd6040518060400160405280600681526020016534206865726560d01b815250611926565b61113c6040518060400160405280601f81526020017f7377617020636f6e74726f6c6c657220757364632062616c616e63652025730081525082611d0e565b6000806000600660009054906101000a90046001600160a01b03166001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561118f57600080fd5b505afa1580156111a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c79190613858565b9250925092506112156040518060400160405280601c81526020017f52657365727665732061667465722063616c6c6261636b203020257300000000815250846001600160701b0316611d0e565b61125d6040518060400160405280601c81526020017f52657365727665732061667465722063616c6c6261636b203120257300000000815250836001600160701b0316611d0e565b6003546001600160a01b0316635c11d795878760113361127f61012c426142e4565b6040518663ffffffff1660e01b815260040161129f959493929190614270565b600060405180830381600087803b1580156112b957600080fd5b505af11580156112cd573d6000803e3d6000fd5b5050600180555050505050505050565b600d818154811061043257600080fd5b336112f6610c8e565b6001600160a01b03161461131c5760405162461bcd60e51b815260040161047b906141c8565b6001600160a01b0381166113815760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161047b565b61138a81611969565b50565b6113d282826040516024016113a3929190614147565b60408051601f198184030181529190526020810180516001600160e01b031663319af33360e01b179052611d4f565b5050565b61142e846323b872dd60e01b8585856040516024016113f79392919061405a565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611d70565b50505050565b8015806114bd5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561148357600080fd5b505afa158015611497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bb91906138be565b155b6115285760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161047b565b6115478363095ea7b360e01b84846040516024016113f792919061407e565b505050565b600061155785611e42565b826001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561159057600080fd5b505afa1580156115a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c89190613649565b6001600160a01b0316856001600160a01b031614806116685750826001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561161b57600080fd5b505afa15801561162f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116539190613649565b6001600160a01b0316856001600160a01b0316145b15611863576000806000856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156116ab57600080fd5b505afa1580156116bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e39190613649565b90506000866001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561172057600080fd5b505afa158015611734573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117589190613649565b9050816001600160a01b0316896001600160a01b031614611779578161177b565b805b93506117b1878a8a6000815181106117a357634e487b7160e01b600052603260045260246000fd5b602002602001015185611ee5565b9250505060006117c4888385308a611fca565b9050866001815181106117e757634e487b7160e01b600052603260045260246000fd5b602002602001015181101561180e5760405162461bcd60e51b815260040161047b90614193565b61185986898561184f868c60008151811061183957634e487b7160e01b600052603260045260246000fd5b602002602001015161226a90919063ffffffff16565b853060008c6122c6565b93505050506118ae565b600061189a868660008151811061188a57634e487b7160e01b600052603260045260246000fd5b6020026020010151306000612438565b90506118aa8482306000876126c9565b9150505b836002815181106118cf57634e487b7160e01b600052603260045260246000fd5b602002602001015181101561191e5760405162461bcd60e51b81526020600482015260156024820152742d30b81d102434b3b41029b634b83830b3b29024b760591b604482015260640161047b565b949350505050565b61138a8160405160240161193a9190614134565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b179052611d4f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006119c485611e42565b6000806000806000899050806001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611a0857600080fd5b505afa158015611a1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a409190613649565b9450806001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015611a7b57600080fd5b505afa158015611a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab39190613649565b600354604051635d5155ef60e11b81526001600160a01b0388811660048301528084166024830152604482018d905260006064830181905260848301523060a48301524260c483015292965091169063baa2abde9060e4016040805180830381600087803b158015611b2457600080fd5b505af1158015611b38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5c91906138f7565b909350915060009050611b6e85611e42565b611b7784611e42565b6007546001600160a01b0389811691161415611bf4576007546000906001600160a01b0387811691161480611bb957506007546001600160a01b038681169116145b611bc4576000611bc6565b8a5b9050611bd486853084612438565b9150611be285843084612438565b611bec90836142e4565b915050611c60565b6000856001600160a01b0316896001600160a01b03161480611c275750846001600160a01b0316896001600160a01b0316145b611c32576000611c34565b8a5b9050611c4386858b3085611fca565b9150611c5285848b3085611fca565b611c5c90836142e4565b9150505b86811015611ca95760405162461bcd60e51b815260206004820152601660248201527516985c0e88121a59da0814db1a5c1c1859d94813dd5d60521b604482015260640161047b565b6007546001600160a01b0389811691161415611cce57611cc93082612c39565b611ce2565b611ce26001600160a01b0389163083611cef565b9998505050505050505050565b6115478363a9059cbb60e01b84846040516024016113f792919061407e565b6113d28282604051602401611d24929190614171565b60408051601f198184030181529190526020810180516001600160e01b03166309710a9d60e41b1790525b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b6000611dc5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d139092919063ffffffff16565b8051909150156115475780806020019051810190611de39190613838565b6115475760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161047b565b600354604051636eb1769f60e11b81523060048201526001600160a01b0391821660248201529082169063dd62ed3e9060440160206040518083038186803b158015611e8d57600080fd5b505afa158015611ea1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec591906138be565b61138a5760035461138a906001600160a01b038381169116600019611434565b600060328082600080896001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015611f2757600080fd5b505afa158015611f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5f9190613858565b506001600160701b031691506001600160701b031691506000876001600160a01b03168a6001600160a01b031614611f975781611f99565b825b90506000611fa96127108661226a565b9050611fb6828b83612d2c565b97505050505050505061191e565b90612e20565b6000836001600160a01b0316866001600160a01b03161415612011576001600160a01b038316301461200a5761200a6001600160a01b0387168487611cef565b5083612261565b604080516002808252606082018352600092602083019080368337019050509050868160008151811061205457634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050848160018151811061209657634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280516060901561214e576003546040516338ed173960e01b81526001600160a01b03909116906338ed1739906120f1908a9060019087908b904290600401614234565b600060405180830381600087803b15801561210b57600080fd5b505af115801561211f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526121479190810190613744565b9050612227565b6001600160a01b038416156121e5576040805160018082528183019092529060208083019080368337019050509150838260008151811061219f57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526003546040516338ed173960e01b81529116906338ed1739906120f1908a9060019087908b904290600401614234565b60405162461bcd60e51b8152602060048201526017602482015276046697265426972645a61703a202170617468207377617604c1b604482015260640161047b565b8060018251612236919061433b565b8151811061225457634e487b7160e01b600052603260045260246000fd5b6020026020010151925050505b95945050505050565b600082612277838261433b565b91508111156122c05760405162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b604482015260640161047b565b92915050565b60006122d188611e42565b6122da87611e42565b60035460405162e8e33760e81b81526001600160a01b038a811660048301528981166024830152604482018990526064820188905260016084830181905260a483015286811660c48301524260e4830152600092839291169063e8e337009061010401606060405180830381600087803b15801561235757600080fd5b505af115801561236b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238f9190613945565b9450909250905060006123a2898461226a565b905084806123c957506123c6612710611fc46008548c612db990919063ffffffff16565b81115b156123df5780156123df576123df8b3383612e76565b60006123eb898461226a565b90508580612412575061240f612710611fc46008548c612db990919063ffffffff16565b81115b15612428578015612428576124288b3383612e76565b5050505098975050505050505050565b6007546000906001600160a01b038681169116141561246f57600754612468906001600160a01b03168486612e76565b508261191e565b60408051600280825260608201835260009260208301908036833701905050905085816000815181106124b257634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526007548251911690829060019081106124f157634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528051606090156125a9576003546040516318cbafe560e01b81526001600160a01b03909116906318cbafe59061254c90899060019087908b904290600401614234565b600060405180830381600087803b15801561256657600080fd5b505af115801561257a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526125a29190810190613744565b9050612688565b6001600160a01b0384161561264057604080516001808252818301909252906020808301908036833701905050915083826000815181106125fa57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526003546040516318cbafe560e01b81529116906318cbafe59061254c90899060019087908b904290600401614234565b60405162461bcd60e51b815260206004820152601b60248201527f46697265426972645a61703a20217061746820546f6b656e424e420000000000604482015260640161047b565b8060018251612697919061433b565b815181106126b557634e487b7160e01b600052603260045260246000fd5b602002602001015192505050949350505050565b600080869050600760009054906101000a90046001600160a01b03166001600160a01b0316876001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561272757600080fd5b505afa15801561273b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275f9190613649565b6001600160a01b031614806127f957506007546040805163d21220a760e01b815290516001600160a01b03928316928a169163d21220a7916004808301926020929190829003018186803b1580156127b657600080fd5b505afa1580156127ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ee9190613649565b6001600160a01b0316145b15612aed576000600760009054906101000a90046001600160a01b03166001600160a01b0316886001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561285857600080fd5b505afa15801561286c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128909190613649565b6001600160a01b03161461291457876001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156128d757600080fd5b505afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290f9190613649565b612985565b876001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561294d57600080fd5b505afa158015612961573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129859190613649565b90506000612a1a83600760009054906101000a90046001600160a01b03168a8c6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156129dd57600080fd5b505afa1580156129f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a159190613649565b611ee5565b90506000612a2a83833087612f22565b905086811015612a4c5760405162461bcd60e51b815260040161047b90614193565b6000612a588a8461226a565b9050600760009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612aaa57600080fd5b505af1158015612abe573d6000803e3d6000fd5b5050600754612ae293508892506001600160a01b031690508684868e60008e6122c6565b955050505050612c2f565b6000876001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015612b2857600080fd5b505afa158015612b3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b609190613649565b90506000886001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015612b9d57600080fd5b505afa158015612bb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd59190613649565b9050600080603281612bec6064611fc48e85612db9565b9050612bfb8682306000612f22565b9350612c1385612c0b8e8461226a565b306000612f22565b92505050612c2885858585858e60008e6122c6565b9550505050505b5095945050505050565b604080516000808252602082019092526001600160a01b038416908390604051612c63919061403e565b60006040518083038185875af1925050503d8060008114612ca0576040519150601f19603f3d011682016040523d82523d6000602084013e612ca5565b606091505b50509050806115475760405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527308115512081d1c985b9cd9995c8819985a5b195960621b606482015260840161047b565b6060612d2284846000856131ed565b90505b9392505050565b6000612d39826002612db9565b612daf612d52612d4b8561271061331e565b8790612db9565b612da9612da4612d83612d678861271061331e565b612d7d612d768a61271061331e565b8c90612db9565b90612db9565b612d9388612d7d8b619c40612db9565b612d9d91906142e4565b8990612db9565b613373565b9061226a565b612d2291906142fc565b6000811580612ddd57508282612dcf818361431c565b9250612ddb90836142fc565b145b6122c05760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604482015260640161047b565b6000808211612e6c5760405162461bcd60e51b815260206004820152601860248201527764732d6d6174682d6469766973696f6e2d62792d7a65726f60401b604482015260640161047b565b612d2582846142fc565b80612e8057505050565b6007546001600160a01b0384811691161415612f0e57600754604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b158015612edc57600080fd5b505af1158015612ef0573d6000803e3d6000fd5b505050506001600160a01b0382163014611547576115478282612c39565b6115476001600160a01b0384168383611cef565b6007546000906001600160a01b0386811691161415612fcc57600760009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f8b57600080fd5b505af1158015612f9f573d6000803e3d6000fd5b505050506001600160a01b0384163014905061246857600754612468906001600160a01b03168486611cef565b604080516002808252606082018352600092602083019080368337505060075482519293506001600160a01b03169183915060009061301b57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050858160018151811061305d57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280516060901561310e57600354604051637ff36ab560e01b81526001600160a01b0390911690637ff36ab59088906130b89060019087908b9042906004016140ff565b6000604051808303818588803b1580156130d157600080fd5b505af11580156130e5573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526125a29190810190613744565b6001600160a01b038416156131a5576040805160018082528183019092529060208083019080368337019050509150838260008151811061315f57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152600354604051637ff36ab560e01b8152911690637ff36ab59088906130b89060019087908b9042906004016140ff565b60405162461bcd60e51b815260206004820152601b60248201527f46697265426972645a61703a20217061746820424e42546f6b656e0000000000604482015260640161047b565b60608247101561324e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161047b565b6001600160a01b0385163b6132a55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161047b565b600080866001600160a01b031685876040516132c1919061403e565b60006040518083038185875af1925050503d80600081146132fe576040519150601f19603f3d011682016040523d82523d6000602084013e613303565b606091505b50915091506133138282866133e3565b979650505050505050565b60008261332b83826142e4565b91508110156122c05760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b604482015260640161047b565b600060038211156133d4575080600061338d6002836142fc565b6133989060016142e4565b90505b818110156133ce579050806002816133b381866142fc565b6133bd91906142e4565b6133c791906142fc565b905061339b565b50919050565b81156133de575060015b919050565b606083156133f2575081612d25565b8251156134025782518084602001fd5b8160405162461bcd60e51b815260040161047b9190614134565b828054828255906000526020600020908101928215613471579160200282015b8281111561347157825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061343c565b5061347d92915061351e565b5090565b82805482825590600052602060002090601f016020900481019282156134715791602002820160005b838211156134e857835183826101000a81548160ff021916908360ff16021790555092602001926001016020816000010492830192600103026134aa565b80156135155782816101000a81549060ff02191690556001016020816000010492830192600103026134e8565b505061347d9291505b5b8082111561347d576000815560010161351f565b600082601f830112613543578081fd5b81356020613558613553836142c0565b61428f565b80838252828201915082860187848660051b8901011115613577578586fd5b855b8581101561359e57813561358c816143aa565b84529284019290840190600101613579565b5090979650505050505050565b600082601f8301126135bb578081fd5b813560206135cb613553836142c0565b80838252828201915082860187848660051b89010111156135ea578586fd5b855b8581101561359e57813560ff81168114613604578788fd5b845292840192908401906001016135ec565b80516001600160701b03811681146133de57600080fd5b60006020828403121561363e578081fd5b8135612d25816143aa565b60006020828403121561365a578081fd5b8151612d25816143aa565b6000806000806080858703121561367a578283fd5b8435613685816143aa565b93506020850135613695816143aa565b925060408501356136a5816143aa565b915060608501356136b5816143aa565b939692955090935050565b6000806000606084860312156136d4578283fd5b833567ffffffffffffffff808211156136eb578485fd5b6136f787838801613533565b9450602086013591508082111561370c578384fd5b61371887838801613533565b9350604086013591508082111561372d578283fd5b5061373a86828701613533565b9150509250925092565b60006020808385031215613756578182fd5b825167ffffffffffffffff81111561376c578283fd5b8301601f8101851361377c578283fd5b805161378a613553826142c0565b80828252848201915084840188868560051b87010111156137a9578687fd5b8694505b838510156137cb5780518352600194909401939185019185016137ad565b50979650505050505050565b600080604083850312156137e9578182fd5b823567ffffffffffffffff80821115613800578384fd5b61380c868387016135ab565b93506020850135915080821115613821578283fd5b5061382e858286016135ab565b9150509250929050565b600060208284031215613849578081fd5b81518015158114612d25578182fd5b60008060006060848603121561386c578283fd5b61387584613616565b925061388360208501613616565b9150604084015163ffffffff8116811461389b578182fd5b809150509250925092565b6000602082840312156138b7578081fd5b5035919050565b6000602082840312156138cf578081fd5b5051919050565b600080604083850312156138e8578182fd5b50508035926020909101359150565b60008060408385031215613909578182fd5b505080516020909101519092909150565b60008060006060848603121561392e578081fd5b505081359360208301359350604090920135919050565b600080600060608486031215613959578081fd5b8351925060208401519150604084015190509250925092565b6000815180845260208085019450808401835b838110156139aa5781516001600160a01b031687529582019590820190600101613985565b509495945050505050565b6000815480845260208085019450838352808320835b838110156139aa5781546001600160a01b0316875295820195600191820191016139cb565b805480835260008281526020808220940193909190825b82601f82011015613c8e57815460ff80821688526020613a30818a01838560081c1660ff169052565b6040613a45818b01848660101c1660ff169052565b6060613a5a818c01858760181c1660ff169052565b6080613a6e818d018688871c1660ff169052565b60a09350613a85848d01868860281c1660ff169052565b60c0613a9a818e01878960301c1660ff169052565b60e0613aaf818f01888a60381c1660ff169052565b60ff88861c8816166101008f0152613ad26101208f01888a60481c1660ff169052565b613ae76101408f01888a60501c1660ff169052565b613afc6101608f01888a60581c1660ff169052565b60ff88851c8816166101808f0152613b1f6101a08f01888a60681c1660ff169052565b613b346101c08f01888a60701c1660ff169052565b613b496101e08f01888a60781c1660ff169052565b60ff88841c8816166102008f0152613b6c6102208f01888a60881c1660ff169052565b613b816102408f01888a60901c1660ff169052565b613b966102608f01888a60981c1660ff169052565b60ff88871c8816166102808f0152613bb96102a08f01888a60a81c1660ff169052565b613bce6102c08f01888a60b01c1660ff169052565b613be36102e08f01888a60b81c1660ff169052565b60ff88831c8816166103008f0152613c066103208f01888a60c81c1660ff169052565b613c1b6103408f01888a60d01c1660ff169052565b613c306103608f01888a60d81c1660ff169052565b60ff88821c8816166103808f0152505050505050613c596103a08901828460e81c1660ff169052565b613c6e6103c08901828460f01c1660ff169052565b5060f81c6103e08701526104009095019460019190910190602001613a07565b90549082811015613ca95760ff821686526020909501946001015b82811015613cc55760ff600883901c1686526020909501946001015b82811015613ce15760ff601083901c1686526020909501946001015b82811015613cfd5760ff601883901c1686526020909501946001015b82811015613d1a57602082901c60ff168652602095909501946001015b82811015613d365760ff602883901c1686526020909501946001015b82811015613d525760ff603083901c1686526020909501946001015b82811015613d6e5760ff603883901c1686526020909501946001015b82811015613d8a5760ff604083901c1686526020909501946001015b82811015613da65760ff604883901c1686526020909501946001015b82811015613dc25760ff605083901c1686526020909501946001015b82811015613dde5760ff605883901c1686526020909501946001015b82811015613dfa5760ff606083901c1686526020909501946001015b82811015613e165760ff606883901c1686526020909501946001015b82811015613e325760ff607083901c1686526020909501946001015b82811015613e4e5760ff607883901c1686526020909501946001015b82811015613e6a5760ff608083901c1686526020909501946001015b82811015613e865760ff608883901c1686526020909501946001015b82811015613ea25760ff609083901c1686526020909501946001015b82811015613ebe5760ff609883901c1686526020909501946001015b82811015613eda5760ff60a083901c1686526020909501946001015b82811015613ef65760ff60a883901c1686526020909501946001015b82811015613f125760ff60b083901c1686526020909501946001015b82811015613f2e5760ff60b883901c1686526020909501946001015b82811015613f4a5760ff60c083901c1686526020909501946001015b82811015613f665760ff60c883901c1686526020909501946001015b82811015613f825760ff60d083901c1686526020909501946001015b82811015613f9e5760ff60d883901c1686526020909501946001015b82811015613fba5760ff60e083901c1686526020909501946001015b82811015613fd65760ff60e883901c1686526020909501946001015b82811015613ff25760ff60f083901c1686526020909501946001015b828110156140085760f882901c86526020860195505b5093949350505050565b6000815180845261402a816020860160208601614352565b601f01601f19169290920160200192915050565b60008251614050818460208701614352565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6060815260006140aa60608301866139b5565b82810360208401526140bc81866139b5565b905082810360408401526140d081856139b5565b9695505050505050565b6040815260006140ed60408301856139f0565b828103602084015261226181856139f0565b8481526080602082015260006141186080830186613972565b6001600160a01b03949094166040830152506060015292915050565b602081526000612d256020830184614012565b60408152600061415a6040830185614012565b905060018060a01b03831660208301529392505050565b6040815260006141846040830185614012565b90508260208301529392505050565b6020808252818101527f5a61703a20496e73756666696369656e74205265636569766520416d6f756e74604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b85815284602082015260a06040820152600061425360a0830186613972565b6001600160a01b0394909416606083015250608001529392505050565b85815284602082015260a06040820152600061425360a08301866139b5565b604051601f8201601f1916810167ffffffffffffffff811182821017156142b8576142b8614394565b604052919050565b600067ffffffffffffffff8211156142da576142da614394565b5060051b60200190565b600082198211156142f7576142f761437e565b500190565b60008261431757634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156143365761433661437e565b500290565b60008282101561434d5761434d61437e565b500390565b60005b8381101561436d578181015183820152602001614355565b8381111561142e5750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461138a57600080fdfea264697066735822122095d52a71b04e6318103606eb49e3eed4a30f8c91450ae09b2c8d7c6117bbf44364736f6c63430008040033