ETH Price: $3,464.21 (+3.91%)
Gas: 5 Gwei

Contract

0x71B3Ba7607Abd0cd35EB398c2a38313f10aa3FdB
 

Overview

ETH Balance

0.0002 ETH

Eth Value

$0.69 (@ $3,464.21/ETH)
Transaction Hash
Method
Block
From
To
Swap And Transfe...184211422023-10-24 15:54:47265 days ago1698162887IN
0x71B3Ba76...f10aa3FdB
0.02036629 ETH0.0085483240
Swap And Transfe...184191922023-10-24 9:21:23265 days ago1698139283IN
0x71B3Ba76...f10aa3FdB
0.01991661 ETH0.0062843820.29006598
Swap And Transfe...184171432023-10-24 2:27:59266 days ago1698114479IN
0x71B3Ba76...f10aa3FdB
0.0509826 ETH0.0116636950.31270211
Transfer Token184156172023-10-23 21:21:23266 days ago1698096083IN
0x71B3Ba76...f10aa3FdB
0 ETH0.003328820.58386479
Swap And Transfe...184134652023-10-23 14:08:35266 days ago1698070115IN
0x71B3Ba76...f10aa3FdB
0.18397594 ETH0.0098038245.64802971
Swap And Transfe...184128572023-10-23 12:05:47266 days ago1698062747IN
0x71B3Ba76...f10aa3FdB
0.18369134 ETH0.0028948513.47984986
Swap And Transfe...184104702023-10-23 4:01:59266 days ago1698033719IN
0x71B3Ba76...f10aa3FdB
0.00305196 ETH0.0031500513.23973858
Swap And Transfe...184095402023-10-23 0:54:59267 days ago1698022499IN
0x71B3Ba76...f10aa3FdB
0.00307677 ETH0.001923569.0126884
Swap And Transfe...184077922023-10-22 19:03:35267 days ago1698001415IN
0x71B3Ba76...f10aa3FdB
0.18843176 ETH0.0029182513.58755639
Swap And Transfe...184061242023-10-22 13:25:35267 days ago1697981135IN
0x71B3Ba76...f10aa3FdB
0.00314764 ETH0.001352026.29670902
Swap And Transfe...184008542023-10-21 19:45:23268 days ago1697917523IN
0x71B3Ba76...f10aa3FdB
0.00375533 ETH0.001882098.76696745
Swap And Transfe...184007742023-10-21 19:29:23268 days ago1697916563IN
0x71B3Ba76...f10aa3FdB
0.18921431 ETH0.001878978.79207022
Swap And Transfe...184005522023-10-21 18:44:59268 days ago1697913899IN
0x71B3Ba76...f10aa3FdB
0.01073255 ETH0.0030943813.36425126
Swap And Transfe...184005392023-10-21 18:42:11268 days ago1697913731IN
0x71B3Ba76...f10aa3FdB
0.00947861 ETH0.0032530214.73317066
Swap And Transfe...183982762023-10-21 11:05:59268 days ago1697886359IN
0x71B3Ba76...f10aa3FdB
0.06433607 ETH0.001781167.10118445
Swap And Transfe...183939982023-10-20 20:44:11269 days ago1697834651IN
0x71B3Ba76...f10aa3FdB
0.1914298 ETH0.0040665518.93444446
Swap And Transfe...183856972023-10-19 16:54:11270 days ago1697734451IN
0x71B3Ba76...f10aa3FdB
0.00659694 ETH0.0027122712.28751691
Swap And Transfe...183847122023-10-19 13:36:35270 days ago1697722595IN
0x71B3Ba76...f10aa3FdB
0 ETH0.0041009315.42756284
Swap And Transfe...183813112023-10-19 2:09:11271 days ago1697681351IN
0x71B3Ba76...f10aa3FdB
0.02667425 ETH0.001689696.74568446
Swap And Transfe...183813032023-10-19 2:07:35271 days ago1697681255IN
0x71B3Ba76...f10aa3FdB
0.00331746 ETH0.001328366.1871805
Swap And Transfe...183796802023-10-18 20:40:11271 days ago1697661611IN
0x71B3Ba76...f10aa3FdB
0.20435154 ETH0.0031136910.28455031
Swap And Transfe...183796662023-10-18 20:37:23271 days ago1697661443IN
0x71B3Ba76...f10aa3FdB
0.20435154 ETH0.0037856112.50387853
Swap And Transfe...183796562023-10-18 20:35:23271 days ago1697661323IN
0x71B3Ba76...f10aa3FdB
0.20435154 ETH0.0038479612.70984659
Swap And Transfe...183796482023-10-18 20:33:47271 days ago1697661227IN
0x71B3Ba76...f10aa3FdB
0 ETH0.0046085514.09510829
Swap And Transfe...183796372023-10-18 20:31:35271 days ago1697661095IN
0x71B3Ba76...f10aa3FdB
0 ETH0.0043992513.45499849
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
184211422023-10-24 15:54:47265 days ago1698162887
0x71B3Ba76...f10aa3FdB
0.0006856 ETH
184211422023-10-24 15:54:47265 days ago1698162887
0x71B3Ba76...f10aa3FdB
0.0006856 ETH
184211422023-10-24 15:54:47265 days ago1698162887
0x71B3Ba76...f10aa3FdB
0.02036629 ETH
184191922023-10-24 9:21:23265 days ago1698139283
0x71B3Ba76...f10aa3FdB
0.00058578 ETH
184191922023-10-24 9:21:23265 days ago1698139283
0x71B3Ba76...f10aa3FdB
0.00058578 ETH
184191922023-10-24 9:21:23265 days ago1698139283
0x71B3Ba76...f10aa3FdB
0.01991661 ETH
184171432023-10-24 2:27:59266 days ago1698114479
0x71B3Ba76...f10aa3FdB
0.00149823 ETH
184171432023-10-24 2:27:59266 days ago1698114479
0x71B3Ba76...f10aa3FdB
0.00149823 ETH
184171432023-10-24 2:27:59266 days ago1698114479
0x71B3Ba76...f10aa3FdB
0.0509826 ETH
184134652023-10-23 14:08:35266 days ago1698070115
0x71B3Ba76...f10aa3FdB
0.0054865 ETH
184134652023-10-23 14:08:35266 days ago1698070115
0x71B3Ba76...f10aa3FdB
0.0054865 ETH
184134652023-10-23 14:08:35266 days ago1698070115
0x71B3Ba76...f10aa3FdB
0.18397594 ETH
184128572023-10-23 12:05:47266 days ago1698062747
0x71B3Ba76...f10aa3FdB
0.00539677 ETH
184128572023-10-23 12:05:47266 days ago1698062747
0x71B3Ba76...f10aa3FdB
0.00539677 ETH
184128572023-10-23 12:05:47266 days ago1698062747
0x71B3Ba76...f10aa3FdB
0.18369134 ETH
184104702023-10-23 4:01:59266 days ago1698033719
0x71B3Ba76...f10aa3FdB
0.00008976 ETH
184104702023-10-23 4:01:59266 days ago1698033719
0x71B3Ba76...f10aa3FdB
0.00008976 ETH
184104702023-10-23 4:01:59266 days ago1698033719
0x71B3Ba76...f10aa3FdB
0.00305196 ETH
184095402023-10-23 0:54:59267 days ago1698022499
0x71B3Ba76...f10aa3FdB
0.00009167 ETH
184095402023-10-23 0:54:59267 days ago1698022499
0x71B3Ba76...f10aa3FdB
0.00009167 ETH
184095402023-10-23 0:54:59267 days ago1698022499
0x71B3Ba76...f10aa3FdB
0.00307677 ETH
184077922023-10-22 19:03:35267 days ago1698001415
0x71B3Ba76...f10aa3FdB
0.00552715 ETH
184077922023-10-22 19:03:35267 days ago1698001415
0x71B3Ba76...f10aa3FdB
0.00552715 ETH
184077922023-10-22 19:03:35267 days ago1698001415
0x71B3Ba76...f10aa3FdB
0.18843176 ETH
184061242023-10-22 13:25:35267 days ago1697981135
0x71B3Ba76...f10aa3FdB
0.00009257 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Transfers

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion, Unlicense license
File 1 of 20 : Transfers.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "../interfaces/IWrappedNativeCurrency.sol";
import "../interfaces/ITransfers.sol";
import "../interfaces/IUniswapRouter.sol";
import "../utils/Sweepable.sol";
import "../permit2/src/interfaces/ISignatureTransfer.sol";

import "hardhat/console.sol";

// @inheritdoc ITransfers
contract Transfers is Context, Ownable, Pausable, ReentrancyGuard, Sweepable, ITransfers {
    using SafeERC20 for IERC20;
    using SafeERC20 for IWrappedNativeCurrency;

    // @dev Map of operator addresses and fee destinations.
    mapping(address => address) private feeDestinations;

    // @dev Map of operator addresses to a map of transfer intent ids that have been processed
    mapping(address => mapping(bytes16 => bool)) private processedTransferIntents;

    // @dev Represents native token of a chain (e.g. ETH or MATIC)
    address private immutable NATIVE_CURRENCY = address(0);

    // @dev Uniswap on-chain contract
    IUniswapRouter private immutable uniswap;

    // @dev permit2 SignatureTransfer contract address. Used for tranferring tokens with a signature instead of a full transaction.
    // See: https://github.com/Uniswap/permit2
    ISignatureTransfer public immutable permit2;

    // @dev Canonical wrapped token for this chain. e.g. (wETH or wMATIC).
    IWrappedNativeCurrency private immutable wrappedNativeCurrency;

    // @param _uniswap The address of the Uniswap V3 swap router
    // @param _wrappedNativeCurrency The address of the wrapped token for this chain
    constructor(
        IUniswapRouter _uniswap,
        ISignatureTransfer _permit2,
        address _initialOperator,
        address _initialFeeDestination,
        IWrappedNativeCurrency _wrappedNativeCurrency
    ) {
        uniswap = _uniswap;
        permit2 = _permit2;
        wrappedNativeCurrency = _wrappedNativeCurrency;

        // Sets an initial operator to enable immediate payment processing
        feeDestinations[_initialOperator] = _initialFeeDestination;
    }

    // @dev Raises errors if the intent is invalid
    // @param _intent The intent to validate
    modifier validIntent(TransferIntent calldata _intent) {
        bytes32 hash = keccak256(
            abi.encodePacked(
                _intent.recipientAmount,
                _intent.deadline,
                _intent.recipient,
                _intent.recipientCurrency,
                _intent.refundDestination,
                _intent.feeAmount,
                _intent.id,
                _intent.operator,
                block.chainid,
                _msgSender(),
                address(this)
            )
        );

        bytes32 signedMessageHash;
        if (_intent.prefix.length == 0) {
            // Use 'default' message prefix.
            signedMessageHash = ECDSA.toEthSignedMessageHash(hash);
        } else {
            // Use custom message prefix.
            signedMessageHash = keccak256(abi.encodePacked(_intent.prefix, hash));
        }

        address signer = ECDSA.recover(signedMessageHash, _intent.signature);

        if (signer != _intent.operator) {
            revert InvalidSignature();
        }

        if (_intent.deadline < block.timestamp) {
            revert ExpiredIntent();
        }

        if (_intent.recipient == address(0)) {
            revert NullRecipient();
        }

        if (processedTransferIntents[_intent.operator][_intent.id]) {
            revert AlreadyProcessed();
        }

        _;
    }

    // @dev Raises an error if the operator in the transfer intent is not registered.
    // @param _intent The intent to validate
    modifier operatorIsRegistered(TransferIntent calldata _intent) {
        if (feeDestinations[_intent.operator] == address(0)) revert OperatorNotRegistered();

        _;
    }

    modifier exactValueSent(TransferIntent calldata _intent) {
        // Make sure the correct value was sent
        uint256 neededAmount = _intent.recipientAmount + _intent.feeAmount;
        if (msg.value > neededAmount) {
            revert InvalidNativeAmount(int256(msg.value - neededAmount));
        } else if (msg.value < neededAmount) {
            revert InvalidNativeAmount(-int256(neededAmount - msg.value));
        }

        _;
    }

    // @inheritdoc ITransfers
    function transferNative(TransferIntent calldata _intent)
        external
        payable
        override
        nonReentrant
        whenNotPaused
        validIntent(_intent)
        operatorIsRegistered(_intent)
        exactValueSent(_intent)
    {
        // Make sure the recipient wants the native currency
        if (_intent.recipientCurrency != NATIVE_CURRENCY) revert IncorrectCurrency(NATIVE_CURRENCY);

        // Complete the payment
        transferFundsToDestinations(_intent);
        succeedPayment(_intent, msg.value, NATIVE_CURRENCY);
    }

    // @inheritdoc ITransfers
    function transferToken(
        TransferIntent calldata _intent,
        Permit2SignatureTransferData calldata _signatureTransferData
    ) external override nonReentrant whenNotPaused validIntent(_intent) operatorIsRegistered(_intent) {
        // Make sure the recipient wants a token and the payer is sending it
        if (
            _intent.recipientCurrency == NATIVE_CURRENCY ||
            _signatureTransferData.permit.permitted.token != _intent.recipientCurrency
        ) {
            revert IncorrectCurrency(_signatureTransferData.permit.permitted.token);
        }

        // Make sure the payer has enough of the payment token
        IERC20 erc20 = IERC20(_intent.recipientCurrency);
        uint256 neededAmount = _intent.recipientAmount + _intent.feeAmount;
        uint256 payerBalance = erc20.balanceOf(_msgSender());
        if (payerBalance < neededAmount) {
            revert InsufficientBalance(neededAmount - payerBalance);
        }

        // Make sure the payer is transferring the right amount to this contract
        if (
            _signatureTransferData.transferDetails.to != address(this) ||
            _signatureTransferData.transferDetails.requestedAmount != neededAmount
        ) {
            revert InvalidTransferDetails();
        }

        // Transfer the payment token to this contract
        permit2.permitTransferFrom(
            _signatureTransferData.permit,
            _signatureTransferData.transferDetails,
            _msgSender(),
            _signatureTransferData.signature
        );

        // Complete the payment
        transferFundsToDestinations(_intent);
        succeedPayment(_intent, neededAmount, _intent.recipientCurrency);
    }

    // @inheritdoc ITransfers
    // @dev Wraps msg.value into wrapped token and transfers to recipient.
    function wrapAndTransfer(TransferIntent calldata _intent)
        external
        payable
        override
        nonReentrant
        whenNotPaused
        validIntent(_intent)
        operatorIsRegistered(_intent)
        exactValueSent(_intent)
    {
        // Make sure the recipient wants to receive the wrapped native currency
        if (_intent.recipientCurrency != address(wrappedNativeCurrency)) revert IncorrectCurrency(NATIVE_CURRENCY);

        // Wrap the sent native currency
        wrappedNativeCurrency.deposit{value: msg.value}();

        // Complete the payment
        transferFundsToDestinations(_intent);
        succeedPayment(_intent, msg.value, NATIVE_CURRENCY);
    }

    // @inheritdoc ITransfers
    // @dev Requires _msgSender() to have approved this contract to use the wrapped token.
    // @dev Unwraps into native token and transfers native token (e.g. ETH) to _intent.recipient.
    function unwrapAndTransfer(
        TransferIntent calldata _intent,
        Permit2SignatureTransferData calldata _signatureTransferData
    ) external override nonReentrant whenNotPaused validIntent(_intent) operatorIsRegistered(_intent) {
        // Make sure the recipient wants the native currency and that the payer is
        // sending the wrapped native currency
        if (
            _intent.recipientCurrency != NATIVE_CURRENCY ||
            _signatureTransferData.permit.permitted.token != address(wrappedNativeCurrency)
        ) {
            revert IncorrectCurrency(_signatureTransferData.permit.permitted.token);
        }

        // Make sure the payer has enough of the wrapped native currency
        uint256 neededAmount = _intent.recipientAmount + _intent.feeAmount;
        uint256 payerBalance = wrappedNativeCurrency.balanceOf(_msgSender());
        if (payerBalance < neededAmount) {
            revert InsufficientBalance(neededAmount - payerBalance);
        }

        // Make sure the payer is transferring the right amount of the wrapped native currency to the contract
        if (
            _signatureTransferData.transferDetails.to != address(this) ||
            _signatureTransferData.transferDetails.requestedAmount != neededAmount
        ) {
            revert InvalidTransferDetails();
        }

        // Transfer the payer's wrapped native currency to the contract
        permit2.permitTransferFrom(
            _signatureTransferData.permit,
            _signatureTransferData.transferDetails,
            _msgSender(),
            _signatureTransferData.signature
        );

        // Complete the payment
        unwrapAndTransferFundsToDestinations(_intent);
        succeedPayment(_intent, neededAmount, address(wrappedNativeCurrency));
    }

    /*------------------------------------------------------------------*\
    | Swap and Transfer
    \*------------------------------------------------------------------*/

    // @inheritdoc ITransfers
    function swapAndTransferUniswapV3Native(TransferIntent calldata _intent, uint24 poolFeesTier)
        external
        payable
        override
        nonReentrant
        whenNotPaused
        validIntent(_intent)
        operatorIsRegistered(_intent)
    {
        // Perform the swap
        uint256 amountSwapped = swapTokens(_intent, address(wrappedNativeCurrency), msg.value, poolFeesTier);

        // Return any native currency not used for the swap
        sendNative(_msgSender(), msg.value - amountSwapped, true);

        // Complete the payment
        unwrapAndTransferFundsToDestinations(_intent);
        succeedPayment(_intent, amountSwapped, NATIVE_CURRENCY);
    }

    // @inheritdoc ITransfers
    function swapAndTransferUniswapV3Token(
        TransferIntent calldata _intent,
        Permit2SignatureTransferData calldata _signatureTransferData,
        uint24 poolFeesTier
    ) external override nonReentrant whenNotPaused validIntent(_intent) operatorIsRegistered(_intent) {
        // Make sure the transfer is to this contract
        if (_signatureTransferData.transferDetails.to != address(this)) {
            revert InvalidTransferDetails();
        }

        // Transfer the payer's tokens to this contract
        permit2.permitTransferFrom(
            _signatureTransferData.permit,
            _signatureTransferData.transferDetails,
            _msgSender(),
            _signatureTransferData.signature
        );

        // Make sure uniswap can move the input tokens
        IERC20 tokenIn = IERC20(_signatureTransferData.permit.permitted.token);

        if (tokenIn.allowance(address(this), address(uniswap)) != 0) {
            tokenIn.safeApprove(address(uniswap), 0);
        }

        tokenIn.safeApprove(address(uniswap), type(uint256).max);

        // Perform the swap
        uint256 maxWillingToPay = _signatureTransferData.transferDetails.requestedAmount;
        uint256 amountSwapped = swapTokens(_intent, address(tokenIn), maxWillingToPay, poolFeesTier);

        // Return any of the input token not used for the swap
        uint256 refundAmount = maxWillingToPay - amountSwapped;
        if (tokenIn.balanceOf(address(this)) < refundAmount) {
            revert SwapRefundFailed();
        }
        tokenIn.safeTransfer(_msgSender(), refundAmount);

        // Complete the payment
        unwrapAndTransferFundsToDestinations(_intent);
        succeedPayment(_intent, amountSwapped, address(tokenIn));
    }

    function swapTokens(
        TransferIntent calldata _intent,
        address tokenIn,
        uint256 maxAmountWillingToPay,
        uint24 poolFeesTier
    ) internal returns (uint256) {
        // If the seller is requesting native currency, we need to swap for the wrapped
        // version of that currency first, then unwrap it and send it to the seller.
        address tokenOut = _intent.recipientCurrency == NATIVE_CURRENCY
            ? address(wrappedNativeCurrency)
            : _intent.recipientCurrency;

        uint256 neededAmount = _intent.recipientAmount + _intent.feeAmount;

        // Set up the parameters for exactOutputSingle
        IUniswapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({
            tokenIn: tokenIn,
            tokenOut: tokenOut,
            fee: poolFeesTier,
            recipient: address(this),
            deadline: _intent.deadline,
            amountOut: neededAmount,
            amountInMaximum: maxAmountWillingToPay,
            sqrtPriceLimitX96: 0
        });

        IERC20 tokenOutContract = IERC20(tokenOut);
        uint256 tokenOutBalance = tokenOutContract.balanceOf(address(this));

        // Execute the swap. The exact amount of the provided currency used is returned.
        try uniswap.exactOutputSingle{value: msg.value}(params) returns (uint256 amountSpent) {
            if (tokenOutContract.balanceOf(address(this)) - tokenOutBalance != neededAmount) {
                revert SwapIncorrectOutput();
            }
            // Request any excess native currency be transferred from Uniswap back to this contract
            try uniswap.refundETH() {
                return amountSpent;
            } catch Error(string memory reason) {
                revert RefundFailedString(reason);
            } catch (bytes memory reason) {
                revert RefundFailedBytes(reason);
            }
        } catch Error(string memory reason) {
            revert SwapFailedString(reason);
        } catch (bytes memory reason) {
            revert SwapFailedBytes(reason);
        }
    }

    function transferFundsToDestinations(TransferIntent calldata _intent) internal {
        if (_intent.recipientCurrency == NATIVE_CURRENCY) {
            sendNative(_intent.recipient, _intent.recipientAmount, false);
            sendNative(feeDestinations[_intent.operator], _intent.feeAmount, false);
        } else {
            IERC20 requestedCurrency = IERC20(_intent.recipientCurrency);
            requestedCurrency.safeTransfer(_intent.recipient, _intent.recipientAmount);
            requestedCurrency.safeTransfer(feeDestinations[_intent.operator], _intent.feeAmount);
        }
    }

    function unwrapAndTransferFundsToDestinations(TransferIntent calldata _intent) internal {
        if (_intent.recipientCurrency == NATIVE_CURRENCY) {
            wrappedNativeCurrency.withdraw(_intent.recipientAmount + _intent.feeAmount);
        }
        transferFundsToDestinations(_intent);
    }

    function succeedPayment(
        TransferIntent calldata _intent,
        uint256 spentAmount,
        address spentCurrency
    ) internal {
        processedTransferIntents[_intent.operator][_intent.id] = true;
        emit Transferred(_intent.operator, _intent.id, _intent.recipient, _msgSender(), spentAmount, spentCurrency);
    }

    function sendNative(
        address destination,
        uint256 amount,
        bool isRefund
    ) internal {
        (bool success, bytes memory data) = payable(destination).call{value: amount}("");
        if (!success) {
            revert NativeTransferFailed(destination, amount, isRefund, data);
        }
    }

    // @notice Registers an operator with a custom fee destination.
    function registerOperatorWithFeeDestination(address _feeDestination) public {
        feeDestinations[_msgSender()] = _feeDestination;

        emit OperatorRegistered(_msgSender(), _feeDestination);
    }

    // @notice Registers an operator, using the operator's address as the fee destination.
    function registerOperator() public {
        feeDestinations[_msgSender()] = _msgSender();

        emit OperatorRegistered(_msgSender(), feeDestinations[_msgSender()]);
    }

    function unregisterOperator() public {
        delete feeDestinations[_msgSender()];

        emit OperatorUnregistered(_msgSender());
    }

    // @notice Allows the owner to pause the contract.
    function pause() public onlyOwner {
        _pause();
    }

    // @notice Allows the owner to un-pause the contract.
    function unpause() public onlyOwner {
        _unpause();
    }

    // @dev Required as Uniswap can transfer native tokens to our contract.
    receive() external payable {}
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

File 3 of 20 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

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

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

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

        _;

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

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

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

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

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

File 7 of 20 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

File 8 of 20 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

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

pragma solidity ^0.8.0;

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

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

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

import "../Strings.sol";

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

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

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

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

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

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

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

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

        return (signer, RecoverError.NoError);
    }

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

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

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

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

File 12 of 20 : IUniswapV3SwapCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

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

File 13 of 20 : IPeripheryPayments.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;

/// @title Periphery Payments
/// @notice Functions to ease deposits and withdrawals of ETH
interface IPeripheryPayments {
    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.
    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.
    /// @param amountMinimum The minimum amount of WETH9 to unwrap
    /// @param recipient The address receiving ETH
    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;

    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`
    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps
    /// that use ether for the input amount
    function refundETH() external payable;

    /// @notice Transfers the full amount of a token held by this contract to recipient
    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users
    /// @param token The contract address of the token which will be transferred to `recipient`
    /// @param amountMinimum The minimum amount of token required for a transfer
    /// @param recipient The destination address of the token
    function sweepToken(
        address token,
        uint256 amountMinimum,
        address recipient
    ) external payable;
}

File 14 of 20 : ISwapRouter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';

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

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

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

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

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

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

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

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

File 15 of 20 : ITransfers.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

import "../permit2/src/interfaces/ISignatureTransfer.sol";

// @notice Description of the transfer
// @member recipientAmount Amount of currency to transfer
// @member deadline The timestamp by when the transfer must be in a block.
// @member chainId The chain which the transfer must occur on.
// @member recipient The address which will receive the funds.
// @member recipientCurrency The currency address that amount is priced in.
// @member refundDestination The address which will receive any refunds. If blank, this will be msg.sender.
// @member feeAmount The fee value (in currency) to send to the operator.
// @member id An ID which can be used to track payments.
// @member operator The address of the operator (who created and signed the intent).
// @member signature A hash of all the other struct properties signed by the operator.
// @dev signature=keccak(encodePacked(..allPropsInOrder, chainId, _msgSender(), address(transfersContract))
struct TransferIntent {
    uint256 recipientAmount;
    uint256 deadline;
    address payable recipient;
    address recipientCurrency;
    address refundDestination;
    uint256 feeAmount;
    bytes16 id;
    address operator;
    bytes signature;
    bytes prefix;
}

struct Permit2SignatureTransferData {
    ISignatureTransfer.PermitTransferFrom permit;
    ISignatureTransfer.SignatureTransferDetails transferDetails;
    bytes signature;
}

// @title Transfers Contract
// @notice Functions for making checked transfers between accounts
interface ITransfers {
    // @notice Emitted when a transfer is completed
    // @param operator The operator for the transfer intent
    // @param id The ID of the transfer intent
    // @param recipient Who recieved the funds.
    // @param sender Who sent the funds.
    // @param spentAmount How much the payer sent
    // @param spentCurrency What currency the payer sent
    event Transferred(
        address indexed operator,
        bytes16 id,
        address recipient,
        address sender,
        uint256 spentAmount,
        address spentCurrency
    );

    // @notice Raised when a protocol token transfer fails
    // @param recipient Who the transfer was intended for
    // @param amount The amount of the transfer
    // @param isRefund Whether the transfer was part of a refund
    // @param data The data returned from the failed call
    error NativeTransferFailed(address recipient, uint256 amount, bool isRefund, bytes data);

    // @notice Emitted when an operator is registered
    // @param operator The operator that was registered
    // @param feeDestination The new fee destination for the operator
    event OperatorRegistered(address operator, address feeDestination);

    // @notice Emitted when an operator is unregistered
    // @param operator The operator that was registered
    event OperatorUnregistered(address operator);

    // @notice Raised when the operator in the intent is not registered
    error OperatorNotRegistered();

    // @notice Raised when the intent signature is invalid
    error InvalidSignature();

    // @notice Raised when the invalid amount of native currency is provided
    // @param difference The surplus (or deficit) amount sent
    error InvalidNativeAmount(int256 difference);

    // @notice Raised when the payer does not have enough of the payment token
    // @param difference The balance deficit
    error InsufficientBalance(uint256 difference);

    // @notice Raised when providing an intent with the incorrect currency. e.g. a USDC intent to wrapAndTransfer(..)
    // @param attemptedCurrency The currency the payer attempted to pay with
    error IncorrectCurrency(address attemptedCurrency);

    // @notice Raised when the permit2 transfer details are incorrect
    error InvalidTransferDetails();

    // @notice Raised when an intent is paid past its deadline
    error ExpiredIntent();

    // @notice Raised when an intent's recipient is the null address
    error NullRecipient();

    // @notice Raised when an intent has already been processed
    error AlreadyProcessed();

    // @notice Raised when a refund after a swap fails and returns a reason string
    // @param reason The error reason returned from the swap
    error RefundFailedString(string reason);

    // @notice Raised when a refund after a swap fails and returns another error
    // @param reason The error reason returned from the swap
    error RefundFailedBytes(bytes reason);

    // @notice Raised when a swap fails and returns a reason string
    // @param reason The error reason returned from the swap
    error SwapFailedString(string reason);

    // @notice Raised when a swap fails and returns another error
    // @param reason The error reason returned from the swap
    error SwapFailedBytes(bytes reason);

    // @notice Raised if the swap does not give us enough output token
    error SwapRefundFailed();

    // @notice Raised if the swap does not give us enough output token
    error SwapIncorrectOutput();

    // @notice Transfer the exact amount of currency from the sender to the recipient.
    // @dev If currency is an ERC-20, the user must have approved this contract prior to invoking.
    // @param _intent The intent which describes the transfer
    function transferNative(TransferIntent calldata _intent) external payable;

    // @notice Transfer the exact amount of currency from the sender to the recipient.
    // @dev If currency is an ERC-20, the user must have approved this contract prior to invoking.
    // @param _intent The intent which describes the transfer
    function transferToken(
        TransferIntent calldata _intent,
        Permit2SignatureTransferData calldata _signatureTransferData
    ) external;

    // @notice Takes native currency (e.g. ETH) from the sender and sends wrapped currency (e.g. wETH) to the recipient.
    // @param _intent The intent which describes the transfer
    function wrapAndTransfer(TransferIntent calldata _intent) external payable;

    // @notice Takes wrapped currency (e.g. wETH) from the sender and sends native currency (e.g. ETH) to the recipient.
    // @dev If currency is an ERC-20, the user must have approved this contract prior to invoking.
    // @param _intent The intent which describes the transfer
    function unwrapAndTransfer(
        TransferIntent calldata _intent,
        Permit2SignatureTransferData calldata _signatureTransferData
    ) external;

    // @notice Allows the sender to pay for an intent in any currency using Uniswap.
    // @dev If _providedCurrencyAddress is an ERC-20, the user must have approved this contract prior to invoking.
    // @param _intent The intent which describes the transfer
    // @param _providedCurrencyAddress The currency address which the sender wishes to pay for the intent.
    // @param _maxAmountWillingToPay The maximum amount of _providedCurrencyAddress the sender is willing to pay.
    // @param fee The Uniswap pool fee the user wishes to pay. See: https://docs.uniswap.org/protocol/concepts/V3-overview/fees#pool-fees-tiers
    function swapAndTransferUniswapV3Native(TransferIntent calldata _intent, uint24 poolFeesTier) external payable;

    // @notice Allows the sender to pay for an intent in any currency using Uniswap.
    // @dev If _providedCurrencyAddress is an ERC-20, the user must have approved this contract prior to invoking.
    // @param _intent The intent which describes the transfer
    // @param _providedCurrencyAddress The currency address which the sender wishes to pay for the intent.
    // @param _maxAmountWillingToPay The maximum amount of _providedCurrencyAddress the sender is willing to pay.
    // @param fee The Uniswap pool fee the user wishes to pay. See: https://docs.uniswap.org/protocol/concepts/V3-overview/fees#pool-fees-tiers
    function swapAndTransferUniswapV3Token(
        TransferIntent calldata _intent,
        Permit2SignatureTransferData calldata _signatureTransferData,
        uint24 poolFeesTier
    ) external;
}

File 16 of 20 : IUniswapRouter.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol";

interface IUniswapRouter is ISwapRouter, IPeripheryPayments {}

File 17 of 20 : IWrappedNativeCurrency.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

// @title Represented wrapped (e.g. wETH) currencies
interface IWrappedNativeCurrency is IERC20 {
    function deposit() external payable;

    function withdraw(uint256) external;
}

File 18 of 20 : ISignatureTransfer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/// @title SignatureTransfer
/// @notice Handles ERC20 token transfers through signature based actions
/// @dev Requires user's token approval on the Permit2 contract
interface ISignatureTransfer {
    /// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount
    /// @param maxAmount The maximum amount a spender can request to transfer
    error InvalidAmount(uint256 maxAmount);

    /// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred
    /// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred
    error LengthMismatch();

    /// @notice Emits an event when the owner successfully invalidates an unordered nonce.
    event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);

    /// @notice The token and amount details for a transfer signed in the permit transfer signature
    struct TokenPermissions {
        // ERC20 token address
        address token;
        // the maximum amount that can be spent
        uint256 amount;
    }

    /// @notice The signed permit message for a single token transfer
    struct PermitTransferFrom {
        TokenPermissions permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }

    /// @notice Specifies the recipient address and amount for batched transfers.
    /// @dev Recipients and amounts correspond to the index of the signed token permissions array.
    /// @dev Reverts if the requested amount is greater than the permitted signed amount.
    struct SignatureTransferDetails {
        // recipient address
        address to;
        // spender requested amount
        uint256 requestedAmount;
    }

    /// @notice Used to reconstruct the signed permit message for multiple token transfers
    /// @dev Do not need to pass in spender address as it is required that it is msg.sender
    /// @dev Note that a user still signs over a spender address
    struct PermitBatchTransferFrom {
        // the tokens and corresponding amounts permitted for a transfer
        TokenPermissions[] permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }

    /// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection
    /// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order
    /// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce
    /// @dev It returns a uint256 bitmap
    /// @dev The index, or wordPosition is capped at type(uint248).max
    function nonceBitmap(address, uint256) external view returns (uint256);

    /// @notice Transfers a token using a signed permit message
    /// @dev Reverts if the requested amount is greater than the permitted signed amount
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails The spender's requested transfer details for the permitted token
    /// @param signature The signature to verify
    function permitTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

    /// @notice Transfers a token using a signed permit message
    /// @notice Includes extra data provided by the caller to verify signature over
    /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
    /// @dev Reverts if the requested amount is greater than the permitted signed amount
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails The spender's requested transfer details for the permitted token
    /// @param witness Extra data to include when checking the user signature
    /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
    /// @param signature The signature to verify
    function permitWitnessTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes32 witness,
        string calldata witnessTypeString,
        bytes calldata signature
    ) external;

    /// @notice Transfers multiple tokens using a signed permit message
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails Specifies the recipient and requested amount for the token transfer
    /// @param signature The signature to verify
    function permitTransferFrom(
        PermitBatchTransferFrom memory permit,
        SignatureTransferDetails[] calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

    /// @notice Transfers multiple tokens using a signed permit message
    /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
    /// @notice Includes extra data provided by the caller to verify signature over
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails Specifies the recipient and requested amount for the token transfer
    /// @param witness Extra data to include when checking the user signature
    /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
    /// @param signature The signature to verify
    function permitWitnessTransferFrom(
        PermitBatchTransferFrom memory permit,
        SignatureTransferDetails[] calldata transferDetails,
        address owner,
        bytes32 witness,
        string calldata witnessTypeString,
        bytes calldata signature
    ) external;

    /// @notice Invalidates the bits specified in mask for the bitmap at the word position
    /// @dev The wordPos is maxed at type(uint248).max
    /// @param wordPos A number to index the nonceBitmap at
    /// @param mask A bitmap masked against msg.sender's current bitmap at the word position
    function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;
}

File 19 of 20 : Sweepable.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

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

// @title Sweepable contract
// @notice Implements a role that can sweep stuck funds to an address provided
//   at the time of the call
abstract contract Sweepable is Context, Ownable {
    using SafeERC20 for IERC20;

    // @dev The address of the current sweeper
    address private _sweeper;

    // @dev Restricts the caller to the current sweeper
    modifier onlySweeper() {
        require(sweeper() == _msgSender(), "Sweepable: not the sweeper");
        _;
    }

    // @dev Returns the current sweeper
    function sweeper() public view virtual returns (address) {
        return _sweeper;
    }

    // @dev Sets the sweeper
    // @notice To remove the sweeper role entirely, set this to the zero address.
    function setSweeper(address newSweeper) public virtual onlyOwner {
        _sweeper = newSweeper;
    }

    // @dev Sweeps the entire ETH balance to `destination`
    function sweepETH(address payable destination) public virtual onlySweeper {
        uint256 balance = address(this).balance;
        require(balance > 0, "Sweepable: zero balance");
        (bool success, ) = destination.call{value: balance}("");
        require(success, "Sweepable: transfer error");
    }

    // @dev Sweeps a specific ETH `amount` to `destination`
    function sweepETHAmount(address payable destination, uint256 amount) public virtual onlySweeper {
        uint256 balance = address(this).balance;
        require(balance >= amount, "Sweepable: insufficient balance");
        (bool success, ) = destination.call{value: amount}("");
        require(success, "Sweepable: transfer error");
    }

    // @dev Sweeps the entire token balance to `destination`
    function sweepToken(address _token, address destination) public virtual onlySweeper {
        IERC20 token = IERC20(_token);
        uint256 balance = token.balanceOf(address(this));
        require(balance > 0, "Sweepable: zero balance");
        token.safeTransfer(destination, balance);
    }

    // @dev Sweeps a specific token `amount` to `destination`
    function sweepTokenAmount(
        address _token,
        address destination,
        uint256 amount
    ) public virtual onlySweeper {
        IERC20 token = IERC20(_token);
        uint256 balance = token.balanceOf(address(this));
        require(balance >= amount, "Sweepable: insufficient balance");
        token.safeTransfer(destination, amount);
    }
}

File 20 of 20 : console.sol
// SPDX-License-Identifier: MIT
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(int256 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
	}

	function logUint(uint256 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256)", 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(uint256 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256)", 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(uint256 p0, uint256 p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
	}

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

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

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

	function log(string memory p0, uint256 p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", 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, uint256 p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", 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, uint256 p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", 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(uint256 p0, uint256 p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	function log(string memory p0, string memory p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", 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, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", 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, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", 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, uint256 p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
	}

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

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

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

	function log(bool p0, string memory p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", 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, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", 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, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", 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, uint256 p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
	}

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

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

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

	function log(address p0, string memory p1, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", 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, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", 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, uint256 p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", 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(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

	function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

	function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", 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, uint256 p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

	function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

	function log(bool p0, address p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", 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, uint256 p1, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

	function log(address p0, bool p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
	}

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

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

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

	function log(address p0, address p1, string memory p2, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", 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, uint256 p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", 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));
	}

}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 100000
  },
  "remappings": [],
  "viaIR": true,
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IUniswapRouter","name":"_uniswap","type":"address"},{"internalType":"contract ISignatureTransfer","name":"_permit2","type":"address"},{"internalType":"address","name":"_initialOperator","type":"address"},{"internalType":"address","name":"_initialFeeDestination","type":"address"},{"internalType":"contract IWrappedNativeCurrency","name":"_wrappedNativeCurrency","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyProcessed","type":"error"},{"inputs":[],"name":"ExpiredIntent","type":"error"},{"inputs":[{"internalType":"address","name":"attemptedCurrency","type":"address"}],"name":"IncorrectCurrency","type":"error"},{"inputs":[{"internalType":"uint256","name":"difference","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[{"internalType":"int256","name":"difference","type":"int256"}],"name":"InvalidNativeAmount","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidTransferDetails","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"isRefund","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"NullRecipient","type":"error"},{"inputs":[],"name":"OperatorNotRegistered","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"RefundFailedBytes","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"RefundFailedString","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"SwapFailedBytes","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"SwapFailedString","type":"error"},{"inputs":[],"name":"SwapIncorrectOutput","type":"error"},{"inputs":[],"name":"SwapRefundFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"feeDestination","type":"address"}],"name":"OperatorRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"OperatorUnregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bytes16","name":"id","type":"bytes16"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"spentAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"spentCurrency","type":"address"}],"name":"Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permit2","outputs":[{"internalType":"contract ISignatureTransfer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registerOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeDestination","type":"address"}],"name":"registerOperatorWithFeeDestination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSweeper","type":"address"}],"name":"setSweeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"recipientAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"address","name":"recipientCurrency","type":"address"},{"internalType":"address","name":"refundDestination","type":"address"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes16","name":"id","type":"bytes16"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"prefix","type":"bytes"}],"internalType":"struct TransferIntent","name":"_intent","type":"tuple"},{"internalType":"uint24","name":"poolFeesTier","type":"uint24"}],"name":"swapAndTransferUniswapV3Native","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"recipientAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"address","name":"recipientCurrency","type":"address"},{"internalType":"address","name":"refundDestination","type":"address"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes16","name":"id","type":"bytes16"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"prefix","type":"bytes"}],"internalType":"struct TransferIntent","name":"_intent","type":"tuple"},{"components":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Permit2SignatureTransferData","name":"_signatureTransferData","type":"tuple"},{"internalType":"uint24","name":"poolFeesTier","type":"uint24"}],"name":"swapAndTransferUniswapV3Token","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"destination","type":"address"}],"name":"sweepETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sweepETHAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"destination","type":"address"}],"name":"sweepToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sweepTokenAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sweeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"recipientAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"address","name":"recipientCurrency","type":"address"},{"internalType":"address","name":"refundDestination","type":"address"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes16","name":"id","type":"bytes16"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"prefix","type":"bytes"}],"internalType":"struct TransferIntent","name":"_intent","type":"tuple"}],"name":"transferNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"recipientAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"address","name":"recipientCurrency","type":"address"},{"internalType":"address","name":"refundDestination","type":"address"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes16","name":"id","type":"bytes16"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"prefix","type":"bytes"}],"internalType":"struct TransferIntent","name":"_intent","type":"tuple"},{"components":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Permit2SignatureTransferData","name":"_signatureTransferData","type":"tuple"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unregisterOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"recipientAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"address","name":"recipientCurrency","type":"address"},{"internalType":"address","name":"refundDestination","type":"address"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes16","name":"id","type":"bytes16"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"prefix","type":"bytes"}],"internalType":"struct TransferIntent","name":"_intent","type":"tuple"},{"components":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions","name":"permitted","type":"tuple"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitTransferFrom","name":"permit","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"internalType":"struct ISignatureTransfer.SignatureTransferDetails","name":"transferDetails","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Permit2SignatureTransferData","name":"_signatureTransferData","type":"tuple"}],"name":"unwrapAndTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"recipientAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"address","name":"recipientCurrency","type":"address"},{"internalType":"address","name":"refundDestination","type":"address"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes16","name":"id","type":"bytes16"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"prefix","type":"bytes"}],"internalType":"struct TransferIntent","name":"_intent","type":"tuple"}],"name":"wrapAndTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

61010034620001b457601f620040e538819003918201601f19168301916001600160401b03831184841017620001b95780849260a094604052833981010312620001b4578051906001600160a01b038083168303620001b45760208201518181168103620001b4576200007560408401620001cf565b9060806200008660608601620001cf565b9401518381168103620001b4576040928491600093845498865199338682167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08980a36001600160a81b0319163360ff60a01b191617865560018055608086905260a05260c05260e05216815260036020522080546001600160a01b03191691909216179055613f009081620001e582396080518181816103ed01528181611473015281816118c801528181611e5d01528181612395015281816124080152818161349901528181613a050152613aea015260a051818181610a970152613694015260c0518181816109ca0152818161199201528181611f1401526127a0015260e0518181816114180152818161190401528181611b1801528181612317015281816134db0152613b1d0152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620001b45756fe6080604052600436101561001b575b361561001957600080fd5b005b60e060008035821c631163b2b081146127c457806312261ee71461275557806323d4c2ba146126d3578063258836fe146125d85780632acde0981461253a5780633f4ba83a1461244657806347a8c964146120995780635c975abb146120565780636614eb7114611c18578063715018a614611b7b57806380747a83146116545780638456cb59146115ab57806386489553146115265780638bf122da146111905780638da5cb5b1461113f5780639189a59e146110ed578063a54180af14610ff0578063a876b89a14610f62578063b8d8e48914610e9a578063ccba8aac146106bf578063f2fde38b146105855763fc8f31e01461011b57505061000e565b6101243661287a565b9060015460021415610135906129b7565b6002600155610142612c42565b81359160209283820135936040830161015a81612a1c565b91606085019761016989612a1c565b9261017660808801612a1c565b60a08801359560c089019361018a85612a3d565b908a019661019788612a1c565b928d8b6040519586958d8c8801998a973097339746976102589b9a9894999590918b9792989398885260208801527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000809a81988280978160609d8e1b1660408401528c1b169060540152891b1660688c0152607c8b01527fffffffffffffffffffffffffffffffff0000000000000000000000000000000016609c8a0152851b1660ac88015260c0870152821b1660e08501521b1660f48201526101080190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810182526102889082612ac9565b5190209861012088019961029c8b8a612b0a565b9050156000149a6102d7916102df9c61054c576102b99150612fc1565b6102d16102ca6101008c018c612b0a565b3691612b95565b90612ed4565b9a909a612caf565b73ffffffffffffffffffffffffffffffffffffffff998a8061030088612a1c565b169116036105225742116104f9576103188991612a1c565b16156104cf578761032884612a1c565b168752600482527fffffffffffffffffffffffffffffffff0000000000000000000000000000000061035d6040892092612a3d565b168752815260ff6040872054166104a5578661037a600393612a1c565b16865252846040852054161561047b5761039391612bcc565b938434116000146103d85760246103aa8634612c08565b604051907fb06a5d510000000000000000000000000000000000000000000000000000000082526004820152fd5b8480341061046657506103ea90612a1c565b907f000000000000000000000000000000000000000000000000000000000000000091848316948591160361043557908161042761042e936139dd565b3490613bb3565b6001805580f35b602484604051907f6453b66b0000000000000000000000000000000000000000000000000000000082526004820152fd5b6103aa6104766024923490612c08565b612c15565b60046040517f25ec6c1f000000000000000000000000000000000000000000000000000000008152fd5b60046040517f57eee766000000000000000000000000000000000000000000000000000000008152fd5b60046040517fdf99255c000000000000000000000000000000000000000000000000000000008152fd5b60046040517e80add4000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b61057d61055b6040938d612b0a565b84919451938185928c84019788378201908b8201520389810184520182612ac9565b5190206102b9565b50346106bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc576105bd612834565b6105c5612938565b73ffffffffffffffffffffffffffffffffffffffff80911690811561063857600054827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b80fd5b509034610e96577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc606081360112610e0f5767ffffffffffffffff8060043511610e20576101408260043536030112610e205760243511610e0f57602435360301126106bc5762ffffff6044351660443503610c9957610744600260015414156129b7565b6002600155610751612c42565b6108e16108d9610765604460043501612a1c565b610894610776606460043501612a1c565b91610868610788608460043501612a1c565b9161079760c460043501612a3d565b926107a660e460043501612a1c565b6040805160048035908101356020830152602481013592820192909252606094851b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081168683015298851b8916607482015292841b8816608884015260a40135609c8301527fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941660bc82015292811b851660cc8401524660e084015233811b851661010084015230901b909316610114820152918290610128820190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612ac9565b602081519101206108b061012460043501600435600401612b0a565b15159050610e4e576108c190612fc1565b6102d16102ca61010460043501600435600401612b0a565b919091612caf565b73ffffffffffffffffffffffffffffffffffffffff90818061090760e460043501612a1c565b16911603610522574260246004350135106104f9578061092b604460043501612a1c565b16156104cf578061094060e460043501612a1c565b1682526004602052604082207fffffffffffffffffffffffffffffffff0000000000000000000000000000000061097b60c460043501612a3d565b16835260205260ff6040832054166104a5578061099c60e460043501612a1c565b1682526003602052806040832054161561047b5760846024350130826109c183612a1c565b1603610e2457817f000000000000000000000000000000000000000000000000000000000000000016908360243560040191610a0260c46024350184612b0a565b9094803b15610e2057610a4b95848094604051988995869485937f30f28b7a00000000000000000000000000000000000000000000000000000000855233908c60048701613042565b03925af1928315610e13578493610df6575b5050610a6890612a1c565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008082523060048301527f00000000000000000000000000000000000000000000000000000000000000009490941673ffffffffffffffffffffffffffffffffffffffff8116602483015291909216929091602081604481875afa908115610ca6578591610dc4575b50610d73575b60405190815230600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152602081604481865afa908115610d6757600091610d35575b50610cb157610bab90604051907f095ea7b300000000000000000000000000000000000000000000000000000000602083015260248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff604482015260448152610ba581612aad565b82613137565b60a4602435013590610bd0610bc9604435848460043560040161346c565b8093612c08565b916040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481865afa8015610ca65784918691610c6c575b5010610c4257610c2961042e9333846130d5565b610c37600435600401613ac4565b600435600401613bb3565b60046040517f2a5de760000000000000000000000000000000000000000000000000000000008152fd5b9150506020813d602011610c9e575b81610c8860209383612ac9565b81010312610c995783905138610c15565b600080fd5b3d9150610c7b565b6040513d87823e3d90fd5b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152fd5b906020823d602011610d5f575b81610d4f60209383612ac9565b810103126106bc57505138610b3a565b3d9150610d42565b6040513d6000823e3d90fd5b610dbf6040517f095ea7b30000000000000000000000000000000000000000000000000000000060208201528360248201526000604482015260448152610db981612aad565b84613137565b610afa565b90506020813d602011610dee575b81610ddf60209383612ac9565b81010312610c99575138610af4565b3d9150610dd2565b610e0291929350612a6a565b610e0f5781908338610a5d565b8280fd5b50604051903d90823e3d90fd5b8380fd5b60046040517fed5c6561000000000000000000000000000000000000000000000000000000008152fd5b604090610e8e610e6961012460043501600435600401612b0a565b8491945193818592602084019788378201906020820152036020810184520182612ac9565b5190206108c1565b5080fd5b50346106bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc577fa453db612af59e5521d6ab9284dc3e2d06af286eb1b1b7b771fce4716c19f2c1610f5c610ef6612834565b3380855260036020908152604080872080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff959095169485179055805192835290820192909252918291820190565b0390a180f35b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc573381526003602052604081207fffffffffffffffffffffffff000000000000000000000000000000000000000081541690557f6f42117a557500c705ddf040a619d86f39101e6b74ac20d7b3e5943ba473fc7f6020604051338152a180f35b50346106bc5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57611028612834565b611030612857565b906044359073ffffffffffffffffffffffffffffffffffffffff9061105a82600254163314613d36565b1691604051927f70a08231000000000000000000000000000000000000000000000000000000008452306004850152602084602481845afa938415610ca65785946110b8575b506110b0836110b5951015613e65565b6130d5565b80f35b93506020843d82116110e5575b816110d260209383612ac9565b81010312610c99579251926110b06110a0565b3d91506110c5565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc5773ffffffffffffffffffffffffffffffffffffffff6020915416604051908152f35b507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc906040823601126106bc5760043567ffffffffffffffff8111610e965761014081600401938236030112610e965760243562ffffff81168103610c9957600154600214156111ff906129b7565b600260015561120c612c42565b60448201602483013561121e82612a1c565b61122a60648601612a1c565b9261123760848701612a1c565b92888760c481019461124886612a3d565b9660e48301986112578a612a1c565b60408051963560208089019182529188018990527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606096871b8116878a015293861b8416607489015293851b8316608888015260a49590950135609c8701527fffffffffffffffffffffffffffffffff000000000000000000000000000000009990991660bc86015297821b881660cc8501524660e085015233821b88166101008501523090911b9096166101148301526101088252949061131c61012882612ac9565b5190206101248801978a6113308a82612b0a565b6113659b61135d956102d1946102ca9450610104936114ec57506113549150612fc1565b935b018d612b0a565b979097612caf565b73ffffffffffffffffffffffffffffffffffffffff96878061138688612a1c565b169116036105225742116104f95761139e8691612a1c565b16156104cf57846113ae84612a1c565b168652600482527fffffffffffffffffffffffffffffffff000000000000000000000000000000006113e36040882092612a3d565b168652815260ff6040862054166104a55783611400600393612a1c565b16855252816040842054161561047b5761143e9134907f0000000000000000000000000000000000000000000000000000000000000000168561346c565b916114498334612c08565b92600080808087335af19361145c6132d6565b941561149857509061042e9161147182613ac4565b7f000000000000000000000000000000000000000000000000000000000000000091613bb3565b6040517f28688b5500000000000000000000000000000000000000000000000000000000815233600482015260248101919091526001604482015260806064820152806114e86084820187613306565b0390fd5b6114fb60409361151d92612b0a565b8d8592955194828693838501988937830191820152038d810184520182612ac9565b51902093611356565b50346106bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc576110b581808080611565612834565b6024359073ffffffffffffffffffffffffffffffffffffffff9061158e82600254163314613d36565b61159a83471015613e65565b165af16115a56132d6565b50613e00565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc576115e2612938565b6115ea612c42565b740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8254161781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b509034610e9657611664366128cb565b60019291925460021415611677906129b7565b6002600155611684612c42565b823560209283918286013591604087019061169e82612a1c565b9060608901926116ad84612a1c565b956116ba60808c01612a1c565b968b8960a0820135998a9360c08401976116d389612a3d565b9401988b6116e08b612a1c565b60408051968701928352602083018a9052606093841b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081169184019190915293831b8416605483015293821b83166068820152607c8101969096527fffffffffffffffffffffffffffffffff00000000000000000000000000000000909416609c86015290831b811660ac8501524660c085015233831b811660e08501523090921b90911660f4830152806101088301037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810182526117c29082612ac9565b5190208b61012081016117d58183612b0a565b90501560001461180f9b611807946102d1936102ca93611b4057506117fa9150612fc1565b925b610100810190612b0a565b989098612caf565b73ffffffffffffffffffffffffffffffffffffffff97888061183087612a1c565b169116036105225742116104f9576118488791612a1c565b16156104cf578561185883612a1c565b168a52600488527fffffffffffffffffffffffffffffffff0000000000000000000000000000000061188d60408c2092612a3d565b168a52875260ff60408a2054166104a5576118a88591612a1c565b16885260038652836040892054161561047b576118c490612a1c565b83167f0000000000000000000000000000000000000000000000000000000000000000841614801590611b0a575b611acf579061190091612bcc565b91817f000000000000000000000000000000000000000000000000000000000000000016936040517f70a082310000000000000000000000000000000000000000000000000000000081523360048201528181602481895afa918215611ac4578892611a96575b5050838110611a5c575060808101308361198083612a1c565b1614801590611a4e575b610e245786927f000000000000000000000000000000000000000000000000000000000000000016916119c060c0820182612b0a565b939091813b15611a4a57858094611a08604051978896879586947f30f28b7a000000000000000000000000000000000000000000000000000000008652339160048701613042565b03925af18015611a3f57611a2b575b505082611a2661042e94613ac4565b613bb3565b611a3490612a6a565b610e20578338611a17565b6040513d84823e3d90fd5b8580fd5b508360a0830135141561198a565b611a6860249185612c08565b604051907f926653510000000000000000000000000000000000000000000000000000000082526004820152fd5b90809250813d8311611abd575b611aad8183612ac9565b81010312610c9957513880611967565b503d611aa3565b6040513d8a823e3d90fd5b602483611adb86612a1c565b6040517f6453b66b00000000000000000000000000000000000000000000000000000000815291166004820152fd5b50611b1484612a1c565b83167f0000000000000000000000000000000000000000000000000000000000000000841614156118f2565b6040611b4f611b729288612b0a565b829591955194818692848401988937820190838201520390810184520182612ac9565b519020926117fc565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57611bb2612938565b600073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b509034610e9657611c28366128cb565b611c37600260015414156129b7565b6002600155611c44612c42565b611d90611c5360408401612a1c565b93611d886060850195611d4e611c6888612a1c565b610868611c7760808a01612a1c565b611c8360c08b01612a3d565b92611c8f888c01612a1c565b604080518d356020808301919091528e013591810191909152606097881b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081168983015292881b8316607482015292871b8216608884015260a08c0135609c8401527fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941660bc83015292851b831660cc8201524660e082015233851b83166101008201523090941b9091166101148401528290610128820190565b60208151910120610120860190611d658288612b0a565b1515905061203f57611d779150612fc1565b6102d16102ca610100880188612b0a565b929092612caf565b73ffffffffffffffffffffffffffffffffffffffff918280611db3848801612a1c565b1691160361052257426020850135106104f95781611dd360408601612a1c565b16156104cf5781611de5828601612a1c565b1686526004602052604086207fffffffffffffffffffffffffffffffff00000000000000000000000000000000611e1e60c08701612a3d565b16875260205260ff6040872054166104a557611e3c82918501612a1c565b1685526003602052806040862054161561047b57611e5984612a1c565b81167f00000000000000000000000000000000000000000000000000000000000000008216148015612020575b6120155780611e9485612a1c565b169160246020611ea960a08701358735612bcc565b94604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523360048301525afa90811561200a578791611fd8575b50838110611a5c5750608081013083611f0283612a1c565b1614801590611fca575b610e245786927f00000000000000000000000000000000000000000000000000000000000000001691611f4260c0820182612b0a565b939091813b15611a4a57858094611f8a604051978896879586947f30f28b7a000000000000000000000000000000000000000000000000000000008652339160048701613042565b03925af18015611a3f57611fb6575b5050611fb061042e93611fab846139dd565b612a1c565b91613bb3565b611fbf90612a6a565b610e20578338611f99565b508360a08301351415611f0c565b90506020813d602011612002575b81611ff360209383612ac9565b81010312610c99575138611eea565b3d9150611fe6565b6040513d89823e3d90fd5b611adb602492612a1c565b5061202a82612a1c565b818061203587612a1c565b1691161415611e86565b61204e610e6960409389612b0a565b519020611d77565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc5760ff6020915460a01c166040519015158152f35b506120a33661287a565b600154600214156120b3906129b7565b60026001556120c0612c42565b80356020908183013591604084016120d781612a1c565b9160608601976120e689612a1c565b926120f360808901612a1c565b60a08901359560c08a019361210785612a3d565b908b019661211488612a1c565b604080518981018d8152602081018f9052606096871b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081169382019390935293861b8216605485015295851b81166068840152607c83018b90527fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316609c830152831b821660ac8201524660c082015233831b821660e08201523090921b1660f482015290806101088301037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810182526121f39082612ac9565b519020968861012081016122078183612b0a565b90501560001499611807926122369b61242f57506122259150612fc1565b6102d16102ca6101008d018d612b0a565b73ffffffffffffffffffffffffffffffffffffffff97888061225788612a1c565b169116036105225742116104f95761226f8791612a1c565b16156104cf578561227f84612a1c565b168852600482527fffffffffffffffffffffffffffffffff000000000000000000000000000000006122b460408a2092612a3d565b168852815260ff6040882054166104a557846122d1600393612a1c565b16875252826040862054161561047b576122ea91612bcc565b938434116000146123015760246103aa8634612c08565b8480341061046657506123148291612a1c565b817f00000000000000000000000000000000000000000000000000000000000000001692839116036123dc575082813b156106bc57600491604051928380927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af180156123d1576123bc575b508061239361042e926139dd565b7f0000000000000000000000000000000000000000000000000000000000000000903490613bb3565b916123ca61042e9293612a6a565b9190612385565b6040513d85823e3d90fd5b602490604051907f6453b66b0000000000000000000000000000000000000000000000000000000082527f0000000000000000000000000000000000000000000000000000000000000000166004820152fd5b61055b60409361243e92612b0a565b519020612225565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc5761247d612938565b805460ff8160a01c16156124dc577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152fd5b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc573380825260036020908152604080842080547fffffffffffffffffffffffff000000000000000000000000000000000000000016841790558051838152918201929092527fa453db612af59e5521d6ab9284dc3e2d06af286eb1b1b7b771fce4716c19f2c19181908101610f5c565b50346106bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57612610612834565b612618612857565b9073ffffffffffffffffffffffffffffffffffffffff9061263e82600254163314613d36565b16604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481855afa9182156126c8578492612693575b6110b593506110b0831515613d9b565b91506020833d82116126c0575b816126ad60209383612ac9565b81010312610e20576110b5925191612683565b3d91506126a0565b6040513d86823e3d90fd5b50346106bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc5773ffffffffffffffffffffffffffffffffffffffff612720612834565b612728612938565b167fffffffffffffffffffffffff0000000000000000000000000000000000000000600254161760025580f35b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346106bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc576110b581808080612803612834565b73ffffffffffffffffffffffffffffffffffffffff61282781600254163314613d36565b479161159a831515613d9b565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610c9957565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610c9957565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc90602082820112610c99576004359167ffffffffffffffff8311610c99578261014092030112610c995760040190565b907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91604083820112610c995767ffffffffffffffff90600435828111610c9957610140858284030112610c995760040193602435928311610c99578260e092030112610c995760040190565b73ffffffffffffffffffffffffffffffffffffffff60005416330361295957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b156129be57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3573ffffffffffffffffffffffffffffffffffffffff81168103610c995790565b357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081168103610c995790565b67ffffffffffffffff8111612a7e57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6080810190811067ffffffffffffffff821117612a7e57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612a7e57604052565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610c99570180359067ffffffffffffffff8211610c9957602001918136038313610c9957565b67ffffffffffffffff8111612a7e57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192612ba182612b5b565b91612baf6040519384612ac9565b829481845281830111610c99578281602093846000960137010152565b91908201809211612bd957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b91908203918211612bd957565b7f80000000000000000000000000000000000000000000000000000000000000008114612bd95760000390565b60ff60005460a01c16612c5157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152fd5b6005811015612ea55780612cc05750565b60018103612d265760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152fd5b60028103612d8c5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152fd5b60038103612e185760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152fd5b600414612e2157565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b906041815114600014612f0257612efe916020820151906060604084015193015160001a90612f0c565b9091565b5050600090600290565b9291907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311612fb55760ff16601b81141580612faa575b612f9e579160809493916020936040519384528484015260408301526060820152600093849182805260015afa15610e1357815173ffffffffffffffffffffffffffffffffffffffff811615612f98579190565b50600190565b50505050600090600490565b50601c811415612f44565b50505050600090600390565b60405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c81526060810181811067ffffffffffffffff821117612a7e5760405251902090565b803573ffffffffffffffffffffffffffffffffffffffff8116809103610c99578252602090810135910152565b9394907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0936130aa601f94606073ffffffffffffffffffffffffffffffffffffffff9461308f8a82613015565b604081013560408b0152013560608901526080880190613015565b1660c0850152806101008060e087015285015280610120958686013760008582860101520116010190565b6131359273ffffffffffffffffffffffffffffffffffffffff604051937fa9059cbb00000000000000000000000000000000000000000000000000000000602086015216602484015260448301526044825261313082612aad565b613137565b565b73ffffffffffffffffffffffffffffffffffffffff16906040516040810181811067ffffffffffffffff821117612a7e576040526020928382527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656484830152803b1561327857906131c09160008481959282888195519301915af16131ba6132d6565b90613364565b8051806131ce575b50505050565b81849181010312610e9657820151908115918215036106bc57506131f4578080806131c8565b608490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b606484604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b3d15613301573d906132e782612b5b565b916132f56040519384612ac9565b82523d6000602084013e565b606090565b919082519283825260005b8481106133505750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201613311565b90919015613370575090565b8151156133805750805190602001fd5b6114e8906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b60009060033d116133cb57565b905060046000803e60005160e01c90565b600060443d10613458576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d60248401111761345b57818401948551938411613463573d8501016020848701011161345b575061345892910160200190612ac9565b90565b949350505050565b50949350505050565b93926000946000936060820161348181612a1c565b73ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146000146139ce575073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016925b61350c60a08401358435612bcc565b926040519561010087019287841067ffffffffffffffff851117612a7e5773ffffffffffffffffffffffffffffffffffffffff62ffffff9260209560405216885273ffffffffffffffffffffffffffffffffffffffff871684890152166040870152306060870152013560808501528160a085015260c0840152600060e0840152604051917f70a0823100000000000000000000000000000000000000000000000000000000835230600484015260208360248173ffffffffffffffffffffffffffffffffffffffff85165afa928315610d675760009361399a575b5073ffffffffffffffffffffffffffffffffffffffff60e0604051957fdb3e219800000000000000000000000000000000000000000000000000000000875282815116600488015282602082015116602488015262ffffff60408201511660448801528260608201511660648801526080810151608488015260a081015160a488015260c081015160c488015201511660e485015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926020856101048134885af160009581613966575b506137895750505050506001906136de6133be565b6308c379a014613735575b506136f057565b6114e86136fb6132d6565b6040519182917f917827e1000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b61373d6133dc565b908161374957506136e9565b6114e89250506040519182917f8a627c16000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b602073ffffffffffffffffffffffffffffffffffffffff926024604051809581937f70a08231000000000000000000000000000000000000000000000000000000008352306004840152165afa8015610d6757600090613932575b6137ee9250612c08565b0361390857803b15610c9957600080916004604051809481937f12210e8a0000000000000000000000000000000000000000000000000000000083525af190816138f4575b506138ef57506001906138446133be565b6308c379a01461389b575b5061385657565b6114e86138616132d6565b6040519182917f9aa98b1f000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b6138a36133dc565b90816138af575061384f565b6114e89250506040519182917f8b4d1720000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b925050565b6138ff919350612a6a565b60009138613833565b60046040517f5ddb184e000000000000000000000000000000000000000000000000000000008152fd5b506020823d60201161395e575b8161394c60209383612ac9565b81010312610c99576137ee91516137e4565b3d915061393f565b9095506020813d602011613992575b8161398260209383612ac9565b81010312610c99575194386136c9565b3d9150613975565b9092506020813d6020116139c6575b816139b660209383612ac9565b81010312610c99575191386135e8565b3d91506139a9565b6139d790612a1c565b926134fd565b606081016139ea81612a1c565b73ffffffffffffffffffffffffffffffffffffffff919082167f0000000000000000000000000000000000000000000000000000000000000000831603613a7257509060a061313592613a4c613a4260408501612a1c565b8285359116613cb5565b80613a5960e08501612a1c565b1660005260036020526040600020541691013590613cb5565b9160a082613a8261313595612a1c565b1692613a9e613a9360408501612a1c565b8285359116866130d5565b80613aab60e08501612a1c565b16600052600360205260406000205416910135916130d5565b613ad060608201612a1c565b73ffffffffffffffffffffffffffffffffffffffff9081167f0000000000000000000000000000000000000000000000000000000000000000821614613b1b575b50613135906139dd565b7f00000000000000000000000000000000000000000000000000000000000000001690613b4d60a08201358235612bcc565b823b15610c99576000926024849260405195869384927f2e1a7d4d00000000000000000000000000000000000000000000000000000000845260048401525af1918215610d675761313592613ba4575b5090613b11565b613bad90612a6a565b38613b9d565b9160a0907fb7ee4fafa10d16ee883a136a3dcc9179d8e6041ba71cc29c2b0bce4f7bdd6e869260e085019073ffffffffffffffffffffffffffffffffffffffff92839182613c0085612a1c565b1660005260046020528288613c916040613c8a613c8460c0836000209501997fffffffffffffffffffffffffffffffff000000000000000000000000000000009586613c4b8d612a3d565b166000526020528360002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055612a1c565b98612a3d565b9b01612a1c565b906040519a168a5216602089015233604089015260608801521660808601521692a2565b73ffffffffffffffffffffffffffffffffffffffff16600080808085855af1613cdc6132d6565b9015613ce757505050565b6114e8906040519384937f28688b550000000000000000000000000000000000000000000000000000000085526004850152602484015260006044840152608060648401526084830190613306565b15613d3d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f537765657061626c653a206e6f742074686520737765657065720000000000006044820152fd5b15613da257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f537765657061626c653a207a65726f2062616c616e63650000000000000000006044820152fd5b15613e0757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f537765657061626c653a207472616e73666572206572726f72000000000000006044820152fd5b15613e6c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f537765657061626c653a20696e73756666696369656e742062616c616e6365006044820152fdfea26469706673582212209169435ae840cda11f3165fe743362ae974498a3c68cd08b52d45818173ba23664736f6c63430008110033000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba30000000000000000000000008fccc78dae0a8f93b0fe6799de888d4c57e273db0000000000000000000000006d8675a52438849d90241cb639fba41bdc3329c8000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2

Deployed Bytecode

0x6080604052600436101561001b575b361561001957600080fd5b005b60e060008035821c631163b2b081146127c457806312261ee71461275557806323d4c2ba146126d3578063258836fe146125d85780632acde0981461253a5780633f4ba83a1461244657806347a8c964146120995780635c975abb146120565780636614eb7114611c18578063715018a614611b7b57806380747a83146116545780638456cb59146115ab57806386489553146115265780638bf122da146111905780638da5cb5b1461113f5780639189a59e146110ed578063a54180af14610ff0578063a876b89a14610f62578063b8d8e48914610e9a578063ccba8aac146106bf578063f2fde38b146105855763fc8f31e01461011b57505061000e565b6101243661287a565b9060015460021415610135906129b7565b6002600155610142612c42565b81359160209283820135936040830161015a81612a1c565b91606085019761016989612a1c565b9261017660808801612a1c565b60a08801359560c089019361018a85612a3d565b908a019661019788612a1c565b928d8b6040519586958d8c8801998a973097339746976102589b9a9894999590918b9792989398885260208801527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000809a81988280978160609d8e1b1660408401528c1b169060540152891b1660688c0152607c8b01527fffffffffffffffffffffffffffffffff0000000000000000000000000000000016609c8a0152851b1660ac88015260c0870152821b1660e08501521b1660f48201526101080190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810182526102889082612ac9565b5190209861012088019961029c8b8a612b0a565b9050156000149a6102d7916102df9c61054c576102b99150612fc1565b6102d16102ca6101008c018c612b0a565b3691612b95565b90612ed4565b9a909a612caf565b73ffffffffffffffffffffffffffffffffffffffff998a8061030088612a1c565b169116036105225742116104f9576103188991612a1c565b16156104cf578761032884612a1c565b168752600482527fffffffffffffffffffffffffffffffff0000000000000000000000000000000061035d6040892092612a3d565b168752815260ff6040872054166104a5578661037a600393612a1c565b16865252846040852054161561047b5761039391612bcc565b938434116000146103d85760246103aa8634612c08565b604051907fb06a5d510000000000000000000000000000000000000000000000000000000082526004820152fd5b8480341061046657506103ea90612a1c565b907f000000000000000000000000000000000000000000000000000000000000000091848316948591160361043557908161042761042e936139dd565b3490613bb3565b6001805580f35b602484604051907f6453b66b0000000000000000000000000000000000000000000000000000000082526004820152fd5b6103aa6104766024923490612c08565b612c15565b60046040517f25ec6c1f000000000000000000000000000000000000000000000000000000008152fd5b60046040517f57eee766000000000000000000000000000000000000000000000000000000008152fd5b60046040517fdf99255c000000000000000000000000000000000000000000000000000000008152fd5b60046040517e80add4000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b61057d61055b6040938d612b0a565b84919451938185928c84019788378201908b8201520389810184520182612ac9565b5190206102b9565b50346106bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc576105bd612834565b6105c5612938565b73ffffffffffffffffffffffffffffffffffffffff80911690811561063857600054827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b80fd5b509034610e96577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc606081360112610e0f5767ffffffffffffffff8060043511610e20576101408260043536030112610e205760243511610e0f57602435360301126106bc5762ffffff6044351660443503610c9957610744600260015414156129b7565b6002600155610751612c42565b6108e16108d9610765604460043501612a1c565b610894610776606460043501612a1c565b91610868610788608460043501612a1c565b9161079760c460043501612a3d565b926107a660e460043501612a1c565b6040805160048035908101356020830152602481013592820192909252606094851b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081168683015298851b8916607482015292841b8816608884015260a40135609c8301527fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941660bc82015292811b851660cc8401524660e084015233811b851661010084015230901b909316610114820152918290610128820190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612ac9565b602081519101206108b061012460043501600435600401612b0a565b15159050610e4e576108c190612fc1565b6102d16102ca61010460043501600435600401612b0a565b919091612caf565b73ffffffffffffffffffffffffffffffffffffffff90818061090760e460043501612a1c565b16911603610522574260246004350135106104f9578061092b604460043501612a1c565b16156104cf578061094060e460043501612a1c565b1682526004602052604082207fffffffffffffffffffffffffffffffff0000000000000000000000000000000061097b60c460043501612a3d565b16835260205260ff6040832054166104a5578061099c60e460043501612a1c565b1682526003602052806040832054161561047b5760846024350130826109c183612a1c565b1603610e2457817f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba316908360243560040191610a0260c46024350184612b0a565b9094803b15610e2057610a4b95848094604051988995869485937f30f28b7a00000000000000000000000000000000000000000000000000000000855233908c60048701613042565b03925af1928315610e13578493610df6575b5050610a6890612a1c565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008082523060048301527f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615649490941673ffffffffffffffffffffffffffffffffffffffff8116602483015291909216929091602081604481875afa908115610ca6578591610dc4575b50610d73575b60405190815230600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152602081604481865afa908115610d6757600091610d35575b50610cb157610bab90604051907f095ea7b300000000000000000000000000000000000000000000000000000000602083015260248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff604482015260448152610ba581612aad565b82613137565b60a4602435013590610bd0610bc9604435848460043560040161346c565b8093612c08565b916040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481865afa8015610ca65784918691610c6c575b5010610c4257610c2961042e9333846130d5565b610c37600435600401613ac4565b600435600401613bb3565b60046040517f2a5de760000000000000000000000000000000000000000000000000000000008152fd5b9150506020813d602011610c9e575b81610c8860209383612ac9565b81010312610c995783905138610c15565b600080fd5b3d9150610c7b565b6040513d87823e3d90fd5b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152fd5b906020823d602011610d5f575b81610d4f60209383612ac9565b810103126106bc57505138610b3a565b3d9150610d42565b6040513d6000823e3d90fd5b610dbf6040517f095ea7b30000000000000000000000000000000000000000000000000000000060208201528360248201526000604482015260448152610db981612aad565b84613137565b610afa565b90506020813d602011610dee575b81610ddf60209383612ac9565b81010312610c99575138610af4565b3d9150610dd2565b610e0291929350612a6a565b610e0f5781908338610a5d565b8280fd5b50604051903d90823e3d90fd5b8380fd5b60046040517fed5c6561000000000000000000000000000000000000000000000000000000008152fd5b604090610e8e610e6961012460043501600435600401612b0a565b8491945193818592602084019788378201906020820152036020810184520182612ac9565b5190206108c1565b5080fd5b50346106bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc577fa453db612af59e5521d6ab9284dc3e2d06af286eb1b1b7b771fce4716c19f2c1610f5c610ef6612834565b3380855260036020908152604080872080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff959095169485179055805192835290820192909252918291820190565b0390a180f35b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc573381526003602052604081207fffffffffffffffffffffffff000000000000000000000000000000000000000081541690557f6f42117a557500c705ddf040a619d86f39101e6b74ac20d7b3e5943ba473fc7f6020604051338152a180f35b50346106bc5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57611028612834565b611030612857565b906044359073ffffffffffffffffffffffffffffffffffffffff9061105a82600254163314613d36565b1691604051927f70a08231000000000000000000000000000000000000000000000000000000008452306004850152602084602481845afa938415610ca65785946110b8575b506110b0836110b5951015613e65565b6130d5565b80f35b93506020843d82116110e5575b816110d260209383612ac9565b81010312610c99579251926110b06110a0565b3d91506110c5565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc5773ffffffffffffffffffffffffffffffffffffffff6020915416604051908152f35b507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc906040823601126106bc5760043567ffffffffffffffff8111610e965761014081600401938236030112610e965760243562ffffff81168103610c9957600154600214156111ff906129b7565b600260015561120c612c42565b60448201602483013561121e82612a1c565b61122a60648601612a1c565b9261123760848701612a1c565b92888760c481019461124886612a3d565b9660e48301986112578a612a1c565b60408051963560208089019182529188018990527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606096871b8116878a015293861b8416607489015293851b8316608888015260a49590950135609c8701527fffffffffffffffffffffffffffffffff000000000000000000000000000000009990991660bc86015297821b881660cc8501524660e085015233821b88166101008501523090911b9096166101148301526101088252949061131c61012882612ac9565b5190206101248801978a6113308a82612b0a565b6113659b61135d956102d1946102ca9450610104936114ec57506113549150612fc1565b935b018d612b0a565b979097612caf565b73ffffffffffffffffffffffffffffffffffffffff96878061138688612a1c565b169116036105225742116104f95761139e8691612a1c565b16156104cf57846113ae84612a1c565b168652600482527fffffffffffffffffffffffffffffffff000000000000000000000000000000006113e36040882092612a3d565b168652815260ff6040862054166104a55783611400600393612a1c565b16855252816040842054161561047b5761143e9134907f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2168561346c565b916114498334612c08565b92600080808087335af19361145c6132d6565b941561149857509061042e9161147182613ac4565b7f000000000000000000000000000000000000000000000000000000000000000091613bb3565b6040517f28688b5500000000000000000000000000000000000000000000000000000000815233600482015260248101919091526001604482015260806064820152806114e86084820187613306565b0390fd5b6114fb60409361151d92612b0a565b8d8592955194828693838501988937830191820152038d810184520182612ac9565b51902093611356565b50346106bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc576110b581808080611565612834565b6024359073ffffffffffffffffffffffffffffffffffffffff9061158e82600254163314613d36565b61159a83471015613e65565b165af16115a56132d6565b50613e00565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc576115e2612938565b6115ea612c42565b740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8254161781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b509034610e9657611664366128cb565b60019291925460021415611677906129b7565b6002600155611684612c42565b823560209283918286013591604087019061169e82612a1c565b9060608901926116ad84612a1c565b956116ba60808c01612a1c565b968b8960a0820135998a9360c08401976116d389612a3d565b9401988b6116e08b612a1c565b60408051968701928352602083018a9052606093841b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081169184019190915293831b8416605483015293821b83166068820152607c8101969096527fffffffffffffffffffffffffffffffff00000000000000000000000000000000909416609c86015290831b811660ac8501524660c085015233831b811660e08501523090921b90911660f4830152806101088301037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810182526117c29082612ac9565b5190208b61012081016117d58183612b0a565b90501560001461180f9b611807946102d1936102ca93611b4057506117fa9150612fc1565b925b610100810190612b0a565b989098612caf565b73ffffffffffffffffffffffffffffffffffffffff97888061183087612a1c565b169116036105225742116104f9576118488791612a1c565b16156104cf578561185883612a1c565b168a52600488527fffffffffffffffffffffffffffffffff0000000000000000000000000000000061188d60408c2092612a3d565b168a52875260ff60408a2054166104a5576118a88591612a1c565b16885260038652836040892054161561047b576118c490612a1c565b83167f0000000000000000000000000000000000000000000000000000000000000000841614801590611b0a575b611acf579061190091612bcc565b91817f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216936040517f70a082310000000000000000000000000000000000000000000000000000000081523360048201528181602481895afa918215611ac4578892611a96575b5050838110611a5c575060808101308361198083612a1c565b1614801590611a4e575b610e245786927f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba316916119c060c0820182612b0a565b939091813b15611a4a57858094611a08604051978896879586947f30f28b7a000000000000000000000000000000000000000000000000000000008652339160048701613042565b03925af18015611a3f57611a2b575b505082611a2661042e94613ac4565b613bb3565b611a3490612a6a565b610e20578338611a17565b6040513d84823e3d90fd5b8580fd5b508360a0830135141561198a565b611a6860249185612c08565b604051907f926653510000000000000000000000000000000000000000000000000000000082526004820152fd5b90809250813d8311611abd575b611aad8183612ac9565b81010312610c9957513880611967565b503d611aa3565b6040513d8a823e3d90fd5b602483611adb86612a1c565b6040517f6453b66b00000000000000000000000000000000000000000000000000000000815291166004820152fd5b50611b1484612a1c565b83167f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2841614156118f2565b6040611b4f611b729288612b0a565b829591955194818692848401988937820190838201520390810184520182612ac9565b519020926117fc565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57611bb2612938565b600073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b509034610e9657611c28366128cb565b611c37600260015414156129b7565b6002600155611c44612c42565b611d90611c5360408401612a1c565b93611d886060850195611d4e611c6888612a1c565b610868611c7760808a01612a1c565b611c8360c08b01612a3d565b92611c8f888c01612a1c565b604080518d356020808301919091528e013591810191909152606097881b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081168983015292881b8316607482015292871b8216608884015260a08c0135609c8401527fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941660bc83015292851b831660cc8201524660e082015233851b83166101008201523090941b9091166101148401528290610128820190565b60208151910120610120860190611d658288612b0a565b1515905061203f57611d779150612fc1565b6102d16102ca610100880188612b0a565b929092612caf565b73ffffffffffffffffffffffffffffffffffffffff918280611db3848801612a1c565b1691160361052257426020850135106104f95781611dd360408601612a1c565b16156104cf5781611de5828601612a1c565b1686526004602052604086207fffffffffffffffffffffffffffffffff00000000000000000000000000000000611e1e60c08701612a3d565b16875260205260ff6040872054166104a557611e3c82918501612a1c565b1685526003602052806040862054161561047b57611e5984612a1c565b81167f00000000000000000000000000000000000000000000000000000000000000008216148015612020575b6120155780611e9485612a1c565b169160246020611ea960a08701358735612bcc565b94604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523360048301525afa90811561200a578791611fd8575b50838110611a5c5750608081013083611f0283612a1c565b1614801590611fca575b610e245786927f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31691611f4260c0820182612b0a565b939091813b15611a4a57858094611f8a604051978896879586947f30f28b7a000000000000000000000000000000000000000000000000000000008652339160048701613042565b03925af18015611a3f57611fb6575b5050611fb061042e93611fab846139dd565b612a1c565b91613bb3565b611fbf90612a6a565b610e20578338611f99565b508360a08301351415611f0c565b90506020813d602011612002575b81611ff360209383612ac9565b81010312610c99575138611eea565b3d9150611fe6565b6040513d89823e3d90fd5b611adb602492612a1c565b5061202a82612a1c565b818061203587612a1c565b1691161415611e86565b61204e610e6960409389612b0a565b519020611d77565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc5760ff6020915460a01c166040519015158152f35b506120a33661287a565b600154600214156120b3906129b7565b60026001556120c0612c42565b80356020908183013591604084016120d781612a1c565b9160608601976120e689612a1c565b926120f360808901612a1c565b60a08901359560c08a019361210785612a3d565b908b019661211488612a1c565b604080518981018d8152602081018f9052606096871b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081169382019390935293861b8216605485015295851b81166068840152607c83018b90527fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316609c830152831b821660ac8201524660c082015233831b821660e08201523090921b1660f482015290806101088301037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810182526121f39082612ac9565b519020968861012081016122078183612b0a565b90501560001499611807926122369b61242f57506122259150612fc1565b6102d16102ca6101008d018d612b0a565b73ffffffffffffffffffffffffffffffffffffffff97888061225788612a1c565b169116036105225742116104f95761226f8791612a1c565b16156104cf578561227f84612a1c565b168852600482527fffffffffffffffffffffffffffffffff000000000000000000000000000000006122b460408a2092612a3d565b168852815260ff6040882054166104a557846122d1600393612a1c565b16875252826040862054161561047b576122ea91612bcc565b938434116000146123015760246103aa8634612c08565b8480341061046657506123148291612a1c565b817f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21692839116036123dc575082813b156106bc57600491604051928380927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af180156123d1576123bc575b508061239361042e926139dd565b7f0000000000000000000000000000000000000000000000000000000000000000903490613bb3565b916123ca61042e9293612a6a565b9190612385565b6040513d85823e3d90fd5b602490604051907f6453b66b0000000000000000000000000000000000000000000000000000000082527f0000000000000000000000000000000000000000000000000000000000000000166004820152fd5b61055b60409361243e92612b0a565b519020612225565b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc5761247d612938565b805460ff8160a01c16156124dc577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a180f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152fd5b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc573380825260036020908152604080842080547fffffffffffffffffffffffff000000000000000000000000000000000000000016841790558051838152918201929092527fa453db612af59e5521d6ab9284dc3e2d06af286eb1b1b7b771fce4716c19f2c19181908101610f5c565b50346106bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57612610612834565b612618612857565b9073ffffffffffffffffffffffffffffffffffffffff9061263e82600254163314613d36565b16604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481855afa9182156126c8578492612693575b6110b593506110b0831515613d9b565b91506020833d82116126c0575b816126ad60209383612ac9565b81010312610e20576110b5925191612683565b3d91506126a0565b6040513d86823e3d90fd5b50346106bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc5773ffffffffffffffffffffffffffffffffffffffff612720612834565b612728612938565b167fffffffffffffffffffffffff0000000000000000000000000000000000000000600254161760025580f35b50346106bc57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc57602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3168152f35b50346106bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106bc576110b581808080612803612834565b73ffffffffffffffffffffffffffffffffffffffff61282781600254163314613d36565b479161159a831515613d9b565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610c9957565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610c9957565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc90602082820112610c99576004359167ffffffffffffffff8311610c99578261014092030112610c995760040190565b907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91604083820112610c995767ffffffffffffffff90600435828111610c9957610140858284030112610c995760040193602435928311610c99578260e092030112610c995760040190565b73ffffffffffffffffffffffffffffffffffffffff60005416330361295957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b156129be57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3573ffffffffffffffffffffffffffffffffffffffff81168103610c995790565b357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081168103610c995790565b67ffffffffffffffff8111612a7e57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6080810190811067ffffffffffffffff821117612a7e57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612a7e57604052565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610c99570180359067ffffffffffffffff8211610c9957602001918136038313610c9957565b67ffffffffffffffff8111612a7e57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b929192612ba182612b5b565b91612baf6040519384612ac9565b829481845281830111610c99578281602093846000960137010152565b91908201809211612bd957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b91908203918211612bd957565b7f80000000000000000000000000000000000000000000000000000000000000008114612bd95760000390565b60ff60005460a01c16612c5157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152fd5b6005811015612ea55780612cc05750565b60018103612d265760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152fd5b60028103612d8c5760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152fd5b60038103612e185760846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152fd5b600414612e2157565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b906041815114600014612f0257612efe916020820151906060604084015193015160001a90612f0c565b9091565b5050600090600290565b9291907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311612fb55760ff16601b81141580612faa575b612f9e579160809493916020936040519384528484015260408301526060820152600093849182805260015afa15610e1357815173ffffffffffffffffffffffffffffffffffffffff811615612f98579190565b50600190565b50505050600090600490565b50601c811415612f44565b50505050600090600390565b60405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c81526060810181811067ffffffffffffffff821117612a7e5760405251902090565b803573ffffffffffffffffffffffffffffffffffffffff8116809103610c99578252602090810135910152565b9394907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0936130aa601f94606073ffffffffffffffffffffffffffffffffffffffff9461308f8a82613015565b604081013560408b0152013560608901526080880190613015565b1660c0850152806101008060e087015285015280610120958686013760008582860101520116010190565b6131359273ffffffffffffffffffffffffffffffffffffffff604051937fa9059cbb00000000000000000000000000000000000000000000000000000000602086015216602484015260448301526044825261313082612aad565b613137565b565b73ffffffffffffffffffffffffffffffffffffffff16906040516040810181811067ffffffffffffffff821117612a7e576040526020928382527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656484830152803b1561327857906131c09160008481959282888195519301915af16131ba6132d6565b90613364565b8051806131ce575b50505050565b81849181010312610e9657820151908115918215036106bc57506131f4578080806131c8565b608490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b606484604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b3d15613301573d906132e782612b5b565b916132f56040519384612ac9565b82523d6000602084013e565b606090565b919082519283825260005b8481106133505750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201613311565b90919015613370575090565b8151156133805750805190602001fd5b6114e8906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b60009060033d116133cb57565b905060046000803e60005160e01c90565b600060443d10613458576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d60248401111761345b57818401948551938411613463573d8501016020848701011161345b575061345892910160200190612ac9565b90565b949350505050565b50949350505050565b93926000946000936060820161348181612a1c565b73ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146000146139ce575073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216925b61350c60a08401358435612bcc565b926040519561010087019287841067ffffffffffffffff851117612a7e5773ffffffffffffffffffffffffffffffffffffffff62ffffff9260209560405216885273ffffffffffffffffffffffffffffffffffffffff871684890152166040870152306060870152013560808501528160a085015260c0840152600060e0840152604051917f70a0823100000000000000000000000000000000000000000000000000000000835230600484015260208360248173ffffffffffffffffffffffffffffffffffffffff85165afa928315610d675760009361399a575b5073ffffffffffffffffffffffffffffffffffffffff60e0604051957fdb3e219800000000000000000000000000000000000000000000000000000000875282815116600488015282602082015116602488015262ffffff60408201511660448801528260608201511660648801526080810151608488015260a081015160a488015260c081015160c488015201511660e485015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156416926020856101048134885af160009581613966575b506137895750505050506001906136de6133be565b6308c379a014613735575b506136f057565b6114e86136fb6132d6565b6040519182917f917827e1000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b61373d6133dc565b908161374957506136e9565b6114e89250506040519182917f8a627c16000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b602073ffffffffffffffffffffffffffffffffffffffff926024604051809581937f70a08231000000000000000000000000000000000000000000000000000000008352306004840152165afa8015610d6757600090613932575b6137ee9250612c08565b0361390857803b15610c9957600080916004604051809481937f12210e8a0000000000000000000000000000000000000000000000000000000083525af190816138f4575b506138ef57506001906138446133be565b6308c379a01461389b575b5061385657565b6114e86138616132d6565b6040519182917f9aa98b1f000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b6138a36133dc565b90816138af575061384f565b6114e89250506040519182917f8b4d1720000000000000000000000000000000000000000000000000000000008352602060048401526024830190613306565b925050565b6138ff919350612a6a565b60009138613833565b60046040517f5ddb184e000000000000000000000000000000000000000000000000000000008152fd5b506020823d60201161395e575b8161394c60209383612ac9565b81010312610c99576137ee91516137e4565b3d915061393f565b9095506020813d602011613992575b8161398260209383612ac9565b81010312610c99575194386136c9565b3d9150613975565b9092506020813d6020116139c6575b816139b660209383612ac9565b81010312610c99575191386135e8565b3d91506139a9565b6139d790612a1c565b926134fd565b606081016139ea81612a1c565b73ffffffffffffffffffffffffffffffffffffffff919082167f0000000000000000000000000000000000000000000000000000000000000000831603613a7257509060a061313592613a4c613a4260408501612a1c565b8285359116613cb5565b80613a5960e08501612a1c565b1660005260036020526040600020541691013590613cb5565b9160a082613a8261313595612a1c565b1692613a9e613a9360408501612a1c565b8285359116866130d5565b80613aab60e08501612a1c565b16600052600360205260406000205416910135916130d5565b613ad060608201612a1c565b73ffffffffffffffffffffffffffffffffffffffff9081167f0000000000000000000000000000000000000000000000000000000000000000821614613b1b575b50613135906139dd565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21690613b4d60a08201358235612bcc565b823b15610c99576000926024849260405195869384927f2e1a7d4d00000000000000000000000000000000000000000000000000000000845260048401525af1918215610d675761313592613ba4575b5090613b11565b613bad90612a6a565b38613b9d565b9160a0907fb7ee4fafa10d16ee883a136a3dcc9179d8e6041ba71cc29c2b0bce4f7bdd6e869260e085019073ffffffffffffffffffffffffffffffffffffffff92839182613c0085612a1c565b1660005260046020528288613c916040613c8a613c8460c0836000209501997fffffffffffffffffffffffffffffffff000000000000000000000000000000009586613c4b8d612a3d565b166000526020528360002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055612a1c565b98612a3d565b9b01612a1c565b906040519a168a5216602089015233604089015260608801521660808601521692a2565b73ffffffffffffffffffffffffffffffffffffffff16600080808085855af1613cdc6132d6565b9015613ce757505050565b6114e8906040519384937f28688b550000000000000000000000000000000000000000000000000000000085526004850152602484015260006044840152608060648401526084830190613306565b15613d3d57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f537765657061626c653a206e6f742074686520737765657065720000000000006044820152fd5b15613da257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f537765657061626c653a207a65726f2062616c616e63650000000000000000006044820152fd5b15613e0757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f537765657061626c653a207472616e73666572206572726f72000000000000006044820152fd5b15613e6c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f537765657061626c653a20696e73756666696369656e742062616c616e6365006044820152fdfea26469706673582212209169435ae840cda11f3165fe743362ae974498a3c68cd08b52d45818173ba23664736f6c63430008110033

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

000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba30000000000000000000000008fccc78dae0a8f93b0fe6799de888d4c57e273db0000000000000000000000006d8675a52438849d90241cb639fba41bdc3329c8000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2

-----Decoded View---------------
Arg [0] : _uniswap (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
Arg [1] : _permit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3
Arg [2] : _initialOperator (address): 0x8fcCC78Dae0a8f93B0fE6799de888d4C57e273db
Arg [3] : _initialFeeDestination (address): 0x6D8675A52438849d90241cB639fba41bDC3329c8
Arg [4] : _wrappedNativeCurrency (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Arg [1] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Arg [2] : 0000000000000000000000008fccc78dae0a8f93b0fe6799de888d4c57e273db
Arg [3] : 0000000000000000000000006d8675a52438849d90241cb639fba41bdc3329c8
Arg [4] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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