ETH Price: $3,389.18 (+2.82%)

Token

Deep Whales (DEEPAI)
 

Overview

Max Total Supply

100,000,000 DEEPAI

Holders

545 (0.00%)

Market

Price

$0.01 @ 0.000003 ETH (+10.45%)

Onchain Market Cap

$910,530.57

Circulating Supply Market Cap

$0.00

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
0x: Exchange Proxy Flash Wallet
Balance
0 DEEPAI

Value
$0.00
0x22f9dcf4647084d6c31b2765f6910cd85c178c18
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Deep Whales AI bot is a comprehensive solution that unites essential trading tools in one platform.

Market

Volume (24H):$2,035.73
Market Capitalization:$0.00
Circulating Supply:0.00 DEEPAI
Market Data Source: Coinmarketcap

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
DeepWhales

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 21 : DeepWhales.sol
// SPDX-License-Identifier: MIT

/**
 * Deep Whales AI - An almost unfair advantage
 * TG:  https://t.me/DeepWhalesAI
 * X:   https://x.com/DeepWhalesAI
 * WEB: https://www.deepwhalesai.ai
 */

pragma solidity 0.8.23;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IUniswapV2Router02} from "./IUniswapV2Router02.sol";
import {IUniswapV3Router} from "./IUniswapV3Router.sol";
import {IUniswapV2Factory} from "./IUniswapV2Factory.sol";
import {IUniswapV3Factory} from "./IUniswapV3Factory.sol";

contract DeepWhales is ERC20, Ownable {
    using SafeERC20 for IERC20;

    struct Tax {
        uint256 revShareBuyFee;
        uint256 revShareSellFee;
        uint256 marketingBuyFee;
        uint256 marketingSellFee;
        uint256 totalBuyFee;
        uint256 totalSellFee;
    }

    Tax private TAX_STRUCTURE_1 = Tax(10, 10, 40, 290, 50, 300);
    Tax private TAX_STRUCTURE_2 = Tax(10, 10, 40, 140, 50, 150);
    Tax private TAX_STRUCTURE_3 = Tax(10, 10, 40, 40, 50, 50);
    Tax private TAX_STRUCTURE_4 = Tax(0, 0, 0, 0, 0, 0);
    Tax public CURRENT_TAX_STRUCTURE = TAX_STRUCTURE_4;

    uint256 public maxBuyAmount;
    uint256 public maxSellAmount;
    uint256 public maxWallet;

    IUniswapV2Router02 public immutable uniswapV2Router;
    IUniswapV3Router public immutable uniswapV3Router;
    address public uniswapV2Pair;
    address public uniswapV3Pair;
    bool private v3LPProtectionEnabled;

    bool private swapping;
    uint256 public swapTokensAtAmount;
    address public revShareAddress;
    address public marketingAddress;

    uint256 public tradingActiveBlock = 0;
    mapping(address => bool) public markedAsSniper;

    bool public limitsInEffect = true;
    bool public tradingActive = false;
    bool public swapEnabled = false;

    uint256 public tokensForRevShare;
    uint256 public tokensForMarketing;

    bool public oncePerBlockEnabled = true;
    uint256 private lastSwapBlock;
    uint256 public maxSwapsPerBlock = 1;
    uint256 private swapsThisBlock = 0;

    mapping(address => bool) private _isExcludedFromFees;
    mapping(address => bool) public _isExcludedMaxTransactionAmount;
    mapping(address => bool) public automatedMarketMakerPairs;

    event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
    event EnabledTrading();
    event ExcludeFromFees(address indexed account, bool isExcluded);
    event UpdatedRevShareAddress(address indexed newWallet);
    event UpdatedMarketingAddress(address indexed newWallet);
    event MaxTransactionExclusion(address _address, bool excluded);
    event OwnerForcedSwapBack(uint256 timestamp);
    event TransferForeignToken(address token, uint256 amount);
    event UpdatedTaxStructure(uint8 structure);

    constructor(
        address _revShareWallet,
        address _marketingWallet
    ) payable ERC20("Deep Whales", "DEEPAI") Ownable(msg.sender) {
        uint256 totalSupply = 100_000_000 * 1e18;

        maxBuyAmount = (totalSupply * 1) / 100; // 2%
        maxSellAmount = (totalSupply * 1) / 100; // 1%
        maxWallet = (totalSupply * 1) / 100; // 2%
        swapTokensAtAmount = (totalSupply * 5) / 10000; // 0.05 %

        revShareAddress = address(_revShareWallet);
        marketingAddress = address(_marketingWallet);

        // initialize V2 router
        uniswapV2Router = IUniswapV2Router02(
            address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D)
        );

        // initialize V3 router
        uniswapV3Router = IUniswapV3Router(
            address(0xE592427A0AEce92De3Edee1F18E0157C05861564)
        );

        v3LPProtectionEnabled = true;

        _excludeFromMaxTransaction(msg.sender, true);
        _excludeFromMaxTransaction(address(this), true);
        _excludeFromMaxTransaction(address(0xdead), true);
        _excludeFromMaxTransaction(address(revShareAddress), true);
        _excludeFromMaxTransaction(address(marketingAddress), true);

        excludeFromFees(msg.sender, true);
        excludeFromFees(address(this), true);
        excludeFromFees(address(0xdead), true);
        excludeFromFees(address(revShareAddress), true);
        excludeFromFees(address(marketingAddress), true);

        uint256 v1TokensToDistribute = 68_000_000 * 1e18;
        uint256 tokensForLiquidity = totalSupply - v1TokensToDistribute;

        require(
            v1TokensToDistribute + tokensForLiquidity == totalSupply,
            "Invalid token distribution"
        );

        _mint(msg.sender, v1TokensToDistribute);
        _mint(address(this), tokensForLiquidity);
    }

    receive() external payable {}

    fallback() external payable {}

    function updateTaxStructure(uint8 _structure) external onlyOwner {
        require(
            _structure > 0 && _structure <= 4,
            "Invalid Tax Structure: Value must be 1, 2, 3 or 4"
        );
        if (_structure == 1) {
            CURRENT_TAX_STRUCTURE = TAX_STRUCTURE_1;
        } else if (_structure == 2) {
            CURRENT_TAX_STRUCTURE = TAX_STRUCTURE_2;
        } else if (_structure == 3) {
            CURRENT_TAX_STRUCTURE = TAX_STRUCTURE_3;
        } else if (_structure == 4) {
            CURRENT_TAX_STRUCTURE = TAX_STRUCTURE_4;
        }
        emit UpdatedTaxStructure(_structure);
    }

    function _excludeFromMaxTransaction(
        address updAds,
        bool isExcluded
    ) private {
        _isExcludedMaxTransactionAmount[updAds] = isExcluded;
        emit MaxTransactionExclusion(updAds, isExcluded);
    }

    function excludeFromMaxTransaction(
        address updAds,
        bool isEx
    ) external onlyOwner {
        if (!isEx) {
            require(
                updAds != uniswapV2Pair,
                "Cannot remove uniswap pair from max txn"
            );
        }
        _isExcludedMaxTransactionAmount[updAds] = isEx;
    }

    function _setAutomatedMarketMakerPair(address pair, bool value) private {
        automatedMarketMakerPairs[pair] = value;
        _excludeFromMaxTransaction(pair, value);
        emit SetAutomatedMarketMakerPair(pair, value);
    }

    function setAutomatedMarketMakerPair(
        address pair,
        bool value
    ) external onlyOwner {
        require(
            pair != uniswapV2Pair,
            "The pair cannot be removed from automatedMarketMakerPairs"
        );
        _setAutomatedMarketMakerPair(pair, value);
        emit SetAutomatedMarketMakerPair(pair, value);
    }

    function excludeFromFees(address account, bool excluded) public onlyOwner {
        _isExcludedFromFees[account] = excluded;
        emit ExcludeFromFees(account, excluded);
    }

    function _update(
        address from,
        address to,
        uint256 amount
    ) internal override {
        // require(to != address(0), "ERC20: transfer to the zero address");
        require(amount > 0, "amount must be greater than 0");

        if (!tradingActive) {
            require(
                _isExcludedFromFees[from] || _isExcludedFromFees[to],
                "Trading is not active."
            );
        } else {
            require(!markedAsSniper[from], "Snipers cannot transfer tokens");
        }

        if (v3LPProtectionEnabled) {
            if (!_isExcludedFromFees[from] && !_isExcludedFromFees[to]) {
                require(
                    from != address(uniswapV3Pair) &&
                        to != address(uniswapV3Pair),
                    "V3 Pool is currently protected, transfers are disabled"
                );
            }
        }

        if (limitsInEffect) {
            if (
                to != address(0xdead) &&
                !_isExcludedFromFees[from] &&
                !_isExcludedFromFees[to]
            ) {
                //when buy
                if (
                    automatedMarketMakerPairs[from] &&
                    !_isExcludedMaxTransactionAmount[to]
                ) {
                    require(
                        amount <= maxBuyAmount,
                        "Buy transfer amount exceeds the max buy."
                    );
                    require(
                        amount + balanceOf(to) <= maxWallet,
                        "Max Wallet Exceeded"
                    );
                }
                //when sell
                else if (
                    automatedMarketMakerPairs[to] &&
                    !_isExcludedMaxTransactionAmount[from]
                ) {
                    require(
                        amount <= maxSellAmount,
                        "Sell transfer amount exceeds the max sell."
                    );
                } else if (!_isExcludedMaxTransactionAmount[to]) {
                    require(
                        amount + balanceOf(to) <= maxWallet,
                        "Max Wallet Exceeded"
                    );
                }
            }
        }

        uint256 contractTokenBalance = balanceOf(address(this));

        bool canSwap = contractTokenBalance >= swapTokensAtAmount;

        if (
            canSwap && swapEnabled && !swapping && automatedMarketMakerPairs[to]
        ) {
            swapping = true;
            swapBack();
            swapping = false;
        }

        bool takeFee = true;
        // if any account belongs to _isExcludedFromFee account then remove the fee
        if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
            takeFee = false;
        }

        uint256 fees = 0;
        // only take fees on buys/sells, do not take on wallet transfers
        if (takeFee) {
            Tax memory tax = CURRENT_TAX_STRUCTURE;
            // on sell

            if (automatedMarketMakerPairs[to] && tax.totalSellFee > 0) {
                fees = (amount * tax.totalSellFee) / 1000;
                tokensForRevShare +=
                    (fees * tax.revShareSellFee) /
                    tax.totalSellFee;

                tokensForMarketing +=
                    (fees * tax.marketingSellFee) /
                    tax.totalSellFee;
            }
            // on buy
            else if (automatedMarketMakerPairs[from] && tax.totalBuyFee > 0) {
                fees = (amount * tax.totalBuyFee) / 1000;
                tokensForRevShare +=
                    (fees * tax.revShareBuyFee) /
                    tax.totalBuyFee;

                tokensForMarketing +=
                    (fees * tax.marketingBuyFee) /
                    tax.totalBuyFee;
            }

            if (fees > 0) {
                super._update(from, address(this), fees);
            }

            amount -= fees;
        }

        super._update(from, to, amount);
    }

    function getExpectedEthForTokens(
        uint256 tokenAmount
    ) public view returns (uint256) {
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();

        uint256[] memory amounts = uniswapV2Router.getAmountsOut(
            tokenAmount,
            path
        );
        return amounts[1];
    }

    function swapTokensForEth(
        uint256 tokenAmount,
        uint256 minOutputAmount
    ) private {
        // generate the uniswap pair path of token -> weth
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();

        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // make the swap
        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            minOutputAmount,
            path,
            address(this),
            block.timestamp
        );
    }

    function swapBack() private {
        if (block.number != lastSwapBlock) {
            lastSwapBlock = block.number;
            swapsThisBlock = 0;
        }

        if (oncePerBlockEnabled && swapsThisBlock >= maxSwapsPerBlock) {
            return;
        }

        uint256 contractBalance = balanceOf(address(this));
        uint256 totalTokensToSwap = tokensForRevShare + tokensForMarketing;

        if (contractBalance == 0 || totalTokensToSwap == 0) {
            return;
        }

        if (contractBalance > swapTokensAtAmount * 15) {
            contractBalance = swapTokensAtAmount * 15;
        }

        // Calculate the minimum output amount (e.g., 95% of expected output)
        uint256 expectedEthOutput = getExpectedEthForTokens(contractBalance);
        uint256 minOutputAmount = (expectedEthOutput * 95) / 100; // 5% slippage tolerance

        swapTokensForEth(contractBalance, minOutputAmount);

        uint256 ethBalance = address(this).balance;
        uint256 ethForRevShare = (ethBalance * tokensForRevShare) /
            totalTokensToSwap;

        tokensForRevShare = 0;
        tokensForMarketing = 0;

        swapsThisBlock += 1;

        Address.sendValue(payable(revShareAddress), ethForRevShare);
        Address.sendValue(payable(marketingAddress), address(this).balance);
    }

    function transferForeignToken(
        address _token,
        address _to
    ) external onlyOwner returns (bool _sent) {
        require(_token != address(0), "_token address cannot be 0");
        require(_to != address(0), "_to address cannot be 0");
        require(
            _token != address(this) || !tradingActive,
            "Can't withdraw native tokens while trading is active"
        );
        uint256 _contractBalance = IERC20(_token).balanceOf(address(this));
        IERC20(_token).safeTransfer(_to, _contractBalance);
        emit TransferForeignToken(_token, _contractBalance);
        return true;
    }

    function setRevShareAddress(address _revShareAddress) external onlyOwner {
        require(
            _revShareAddress != address(0),
            "_revShareAddress address cannot be 0"
        );
        revShareAddress = payable(_revShareAddress);
        emit UpdatedRevShareAddress(_revShareAddress);
    }

    function setMarketingAddress(address _marketingAddress) external onlyOwner {
        require(
            _marketingAddress != address(0),
            "_marketingAddress address cannot be 0"
        );
        marketingAddress = payable(_marketingAddress);
        emit UpdatedMarketingAddress(_marketingAddress);
    }

    function removeLimits() external onlyOwner {
        limitsInEffect = false;
    }

    function restoreLimits() external onlyOwner {
        limitsInEffect = true;
    }

    function flagSniper(address wallet) external onlyOwner {
        require(!markedAsSniper[wallet], "Wallet is already flagged.");
        markedAsSniper[wallet] = true;
    }

    function massFlagSnipers(address[] calldata wallets) external onlyOwner {
        for (uint256 i = 0; i < wallets.length; i++) {
            markedAsSniper[wallets[i]] = true;
        }
    }

    function unflagSniper(address wallet) external onlyOwner {
        require(markedAsSniper[wallet], "Wallet is already not marked.");
        markedAsSniper[wallet] = false;
    }

    function massUnflagSnipers(address[] calldata wallets) external onlyOwner {
        for (uint256 i = 0; i < wallets.length; i++) {
            markedAsSniper[wallets[i]] = false;
        }
    }

    function recoverETH() external onlyOwner {
        bool success;
        (success, ) = address(msg.sender).call{value: address(this).balance}(
            ""
        );
        require(success, "Failed to recover ETH");
    }

    function prepareLaunch() external onlyOwner {
        require(!tradingActive, "Trading is already active, cannot relaunch.");

        // Check if V2 pair exists, if not create it
        address calculatedV2Pair = IUniswapV2Factory(uniswapV2Router.factory())
            .getPair(address(this), uniswapV2Router.WETH());

        if (calculatedV2Pair == address(0)) {
            // create pair
            uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory())
                .createPair(address(this), uniswapV2Router.WETH());
        } else {
            uniswapV2Pair = calculatedV2Pair;
        }

        // Check if V3 pool exists, if not create it
        address calculatedV3Pair = IUniswapV3Factory(uniswapV3Router.factory())
            .getPool(
                address(this),
                uniswapV2Router.WETH(),
                10000 // fee tier
            );

        if (calculatedV3Pair == address(0)) {
            uniswapV3Pair = IUniswapV3Factory(uniswapV3Router.factory())
                .createPool(address(this), uniswapV2Router.WETH(), 10000);
        } else {
            uniswapV3Pair = calculatedV3Pair;
        }

        _excludeFromMaxTransaction(address(uniswapV2Pair), true);
        _setAutomatedMarketMakerPair(address(uniswapV2Pair), true);

        _excludeFromMaxTransaction(address(uniswapV2Router), true);
        excludeFromFees(address(uniswapV2Router), true);

        require(
            address(this).balance > 0,
            "Must have ETH on contract to launch"
        );
        require(
            balanceOf(address(this)) > 0,
            "Must have Tokens on contract to launch"
        );

        _approve(address(this), address(uniswapV2Router), type(uint256).max);
        _approve(address(this), address(uniswapV3Router), type(uint256).max);

        uniswapV2Router.addLiquidityETH{value: address(this).balance}(
            address(this),
            balanceOf(address(this)),
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            msg.sender,
            block.timestamp
        );
    }

    function enableTrading() external onlyOwner {
        require(!tradingActive, "Cannot reenable trading");
        tradingActive = true;
        swapEnabled = true;
        tradingActiveBlock = block.number;
        emit EnabledTrading();
    }

    function prepareForMigration() external onlyOwner {
        limitsInEffect = false;
        swapTokensAtAmount = totalSupply();
        CURRENT_TAX_STRUCTURE = TAX_STRUCTURE_4;
        maxBuyAmount = totalSupply();
        maxSellAmount = totalSupply();
        maxWallet = totalSupply();
        if (balanceOf(address(this)) > 0) {
            super._update(address(this), msg.sender, balanceOf(address(this)));
        }
    }

    function disableV3LPProtection() external onlyOwner {
        require(
            v3LPProtectionEnabled,
            "V3 LP Protection already disabled forever!"
        );
        v3LPProtectionEnabled = false;
    }

    function setSwapRestrictions(
        bool _enabled,
        uint256 _maxSwaps
    ) external onlyOwner {
        require(_maxSwaps > 0, "Max swaps per block must be greater than 0");
        oncePerBlockEnabled = _enabled;
        maxSwapsPerBlock = _maxSwaps;
    }
}

File 2 of 21 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

File 3 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

File 4 of 21 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 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 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

File 5 of 21 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

import {Errors} from "./Errors.sol";

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert Errors.InsufficientBalance(address(this).balance, amount);
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert Errors.FailedCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {Errors.FailedCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

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

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

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
     * of an unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {Errors.FailedCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

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

File 6 of 21 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling 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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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 7 of 21 : IUniswapV2Router02.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;

import "./IUniswapV2Router01.sol";

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

File 8 of 21 : IUniswapV3Router.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ISwapRouter} from "./ISwapRouter.sol";

interface IUniswapV3Router is ISwapRouter {
    function factory() external pure returns (address);
    function weth() external pure returns (address);
}

File 9 of 21 : IUniswapV2Factory.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;

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

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

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

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

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

File 10 of 21 : IUniswapV3Factory.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.23;

/// @title The interface for the Uniswap V3 Factory
/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees
interface IUniswapV3Factory {
    /// @notice Emitted when the owner of the factory is changed
    /// @param oldOwner The owner before the owner was changed
    /// @param newOwner The owner after the owner was changed
    event OwnerChanged(address indexed oldOwner, address indexed newOwner);

    /// @notice Emitted when a pool is created
    /// @param token0 The first token of the pool by address sort order
    /// @param token1 The second token of the pool by address sort order
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
    /// @param tickSpacing The minimum number of ticks between initialized ticks
    /// @param pool The address of the created pool
    event PoolCreated(
        address indexed token0,
        address indexed token1,
        uint24 indexed fee,
        int24 tickSpacing,
        address pool
    );

    /// @notice Emitted when a new fee amount is enabled for pool creation via the factory
    /// @param fee The enabled fee, denominated in hundredths of a bip
    /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee
    event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);

    /// @notice Returns the current owner of the factory
    /// @dev Can be changed by the current owner via setOwner
    /// @return The address of the factory owner
    function owner() external view returns (address);

    /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled
    /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context
    /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee
    /// @return The tick spacing
    function feeAmountTickSpacing(uint24 fee) external view returns (int24);

    /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
    /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
    /// @param tokenA The contract address of either token0 or token1
    /// @param tokenB The contract address of the other token
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
    /// @return pool The pool address
    function getPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external view returns (address pool);

    /// @notice Creates a pool for the given two tokens and fee
    /// @param tokenA One of the two tokens in the desired pool
    /// @param tokenB The other of the two tokens in the desired pool
    /// @param fee The desired fee for the pool
    /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved
    /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments
    /// are invalid.
    /// @return pool The address of the newly created pool
    function createPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external returns (address pool);

    /// @notice Updates the owner of the factory
    /// @dev Must be called by the current owner
    /// @param _owner The new owner of the factory
    function setOwner(address _owner) external;

    /// @notice Enables a fee amount with the given tickSpacing
    /// @dev Fee amounts may never be removed once enabled
    /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)
    /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount
    function enableFeeAmount(uint24 fee, int24 tickSpacing) external;
}

File 11 of 21 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 12 of 21 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 13 of 21 : draft-IERC6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

File 14 of 21 : IERC1363.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 15 of 21 : Errors.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();
}

File 16 of 21 : IUniswapV2Router01.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    )
        external
        payable
        returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable returns (uint[] memory amounts);
    function swapTokensForExactETH(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactTokensForETH(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapETHForExactTokens(
        uint amountOut,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable returns (uint[] memory amounts);

    function quote(
        uint amountA,
        uint reserveA,
        uint reserveB
    ) external pure returns (uint amountB);
    function getAmountOut(
        uint amountIn,
        uint reserveIn,
        uint reserveOut
    ) external pure returns (uint amountOut);
    function getAmountIn(
        uint amountOut,
        uint reserveIn,
        uint reserveOut
    ) external pure returns (uint amountIn);
    function getAmountsOut(
        uint amountIn,
        address[] calldata path
    ) external view returns (uint[] memory amounts);
    function getAmountsIn(
        uint amountOut,
        address[] calldata path
    ) external view returns (uint[] memory amounts);
}

File 17 of 21 : ISwapRouter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.23;
pragma abicoder v2;

import {IUniswapV3SwapCallback} from "./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 18 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 19 of 21 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

File 20 of 21 : IUniswapV3SwapCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.23;

/// @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 21 of 21 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_revShareWallet","type":"address"},{"internalType":"address","name":"_marketingWallet","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"EnabledTrading","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"ExcludeFromFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"},{"indexed":false,"internalType":"bool","name":"excluded","type":"bool"}],"name":"MaxTransactionExclusion","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"OwnerForcedSwapBack","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetAutomatedMarketMakerPair","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferForeignToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newWallet","type":"address"}],"name":"UpdatedMarketingAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newWallet","type":"address"}],"name":"UpdatedRevShareAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"structure","type":"uint8"}],"name":"UpdatedTaxStructure","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"CURRENT_TAX_STRUCTURE","outputs":[{"internalType":"uint256","name":"revShareBuyFee","type":"uint256"},{"internalType":"uint256","name":"revShareSellFee","type":"uint256"},{"internalType":"uint256","name":"marketingBuyFee","type":"uint256"},{"internalType":"uint256","name":"marketingSellFee","type":"uint256"},{"internalType":"uint256","name":"totalBuyFee","type":"uint256"},{"internalType":"uint256","name":"totalSellFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_isExcludedMaxTransactionAmount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"automatedMarketMakerPairs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableV3LPProtection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"excluded","type":"bool"}],"name":"excludeFromFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"updAds","type":"address"},{"internalType":"bool","name":"isEx","type":"bool"}],"name":"excludeFromMaxTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"flagSniper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"getExpectedEthForTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitsInEffect","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"markedAsSniper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"}],"name":"massFlagSnipers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"}],"name":"massUnflagSnipers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxBuyAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSellAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSwapsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oncePerBlockEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prepareForMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"prepareLaunch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restoreLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revShareAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setAutomatedMarketMakerPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marketingAddress","type":"address"}],"name":"setMarketingAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_revShareAddress","type":"address"}],"name":"setRevShareAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"},{"internalType":"uint256","name":"_maxSwaps","type":"uint256"}],"name":"setSwapRestrictions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapTokensAtAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensForMarketing","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensForRevShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingActiveBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"transferForeignToken","outputs":[{"internalType":"bool","name":"_sent","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"unflagSniper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV3Pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV3Router","outputs":[{"internalType":"contract IUniswapV3Router","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_structure","type":"uint8"}],"name":"updateTaxStructure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

600a60c081905260e08190526028610100819052610122610120819052603261014081905261012c610160819052600685905560078590556008849055600992909255808455600b919091556101808390526101a08390526101c0829052608c6101e08190526102008290526096610220819052600c859055600d859055600e849055600f9190915560108290556011556102408390526102608390526102808290526102a08290526102c08190526102e08190526012839055601392909255601481905560155560168190556017556103c0604081905260006103008190526103208190526103408190526103608190526103808190526103a081905260188190556019819055601a819055601b819055601c819055601d819055601e819055601f8190556020819055602181905560228190556023819055602c819055602e805462ffffff191660019081179091556031805460ff191682179055603355603455620051503881900390819083398101604081905262000181916200155e565b336040518060400160405280600b81526020016a44656570205768616c657360a81b8152506040518060400160405280600681526020016544454550414960d01b8152508160039081620001d6919062001634565b506004620001e5828262001634565b5050506001600160a01b0381166200021857604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b62000223816200046d565b506a52b7d2dcc80cd2e400000060646200023f82600162001716565b6200024b919062001736565b60245560646200025d82600162001716565b62000269919062001736565b60255560646200027b82600162001716565b62000287919062001736565b6026556127106200029a82600562001716565b620002a6919062001736565b602955602a80546001600160a01b038086166001600160a01b031992831617909255602b805492851692909116919091179055737a250d5630b4cf539739df2c5dacb4c659f2488d60805273e592427a0aece92de3edee1f18e0157c0586156460a0526028805460ff60a01b1916600160a01b17905562000329336001620004bf565b62000336306001620004bf565b6200034561dead6001620004bf565b602a546200035e906001600160a01b03166001620004bf565b602b5462000377906001600160a01b03166001620004bf565b6200038433600162000522565b6200039130600162000522565b620003a061dead600162000522565b602a54620003b9906001600160a01b0316600162000522565b602b54620003d2906001600160a01b0316600162000522565b6a383f8f62ee6f1ec40000006000620003ec828462001759565b905082620003fb82846200176f565b146200044a5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420746f6b656e20646973747269627574696f6e00000000000060448201526064016200020f565b6200045633836200058b565b6200046230826200058b565b505050505062001931565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216600081815260366020908152604091829020805460ff19168515159081179091558251938452908301527f6b4f1be9103e6cbcd38ca4a922334f2c3109b260130a6676a987f94088fd6746910160405180910390a15050565b6200052c620005c9565b6001600160a01b038216600081815260356020908152604091829020805460ff191685151590811790915591519182527f9d8f7706ea1113d1a167b526eca956215946dd36cc7df39eb16180222d8b5df7910160405180910390a25050565b6001600160a01b038216620005b75760405163ec442f0560e01b8152600060048201526024016200020f565b620005c560008383620005fa565b5050565b6005546001600160a01b03163314620005f85760405163118cdaa760e01b81523360048201526024016200020f565b565b600081116200064c5760405162461bcd60e51b815260206004820152601d60248201527f616d6f756e74206d7573742062652067726561746572207468616e203000000060448201526064016200020f565b602e54610100900460ff16620006f0576001600160a01b03831660009081526035602052604090205460ff16806200069c57506001600160a01b03821660009081526035602052604090205460ff165b620006ea5760405162461bcd60e51b815260206004820152601660248201527f54726164696e67206973206e6f74206163746976652e0000000000000000000060448201526064016200020f565b6200075b565b6001600160a01b0383166000908152602d602052604090205460ff16156200075b5760405162461bcd60e51b815260206004820152601e60248201527f536e69706572732063616e6e6f74207472616e7366657220746f6b656e73000060448201526064016200020f565b602854600160a01b900460ff161562000858576001600160a01b03831660009081526035602052604090205460ff16158015620007b157506001600160a01b03821660009081526035602052604090205460ff16155b1562000858576028546001600160a01b03848116911614801590620007e457506028546001600160a01b03838116911614155b620008585760405162461bcd60e51b815260206004820152603660248201527f563320506f6f6c2069732063757272656e746c792070726f7465637465642c2060448201527f7472616e7366657273206172652064697361626c65640000000000000000000060648201526084016200020f565b602e5460ff161562000b24576001600160a01b03821661dead148015906200089957506001600160a01b03831660009081526035602052604090205460ff16155b8015620008bf57506001600160a01b03821660009081526035602052604090205460ff16155b1562000b24576001600160a01b03831660009081526037602052604090205460ff1680156200090757506001600160a01b03821660009081526036602052604090205460ff16155b15620009e657602454811115620009725760405162461bcd60e51b815260206004820152602860248201527f427579207472616e7366657220616d6f756e742065786365656473207468652060448201526736b0bc10313abc9760c11b60648201526084016200020f565b6026546001600160a01b0383166000908152602081905260409020546200099a90836200176f565b1115620009e05760405162461bcd60e51b815260206004820152601360248201527213585e0815d85b1b195d08115e18d959591959606a1b60448201526064016200020f565b62000b24565b6001600160a01b03821660009081526037602052604090205460ff16801562000a2857506001600160a01b03831660009081526036602052604090205460ff16155b1562000a9557602554811115620009e05760405162461bcd60e51b815260206004820152602a60248201527f53656c6c207472616e7366657220616d6f756e742065786365656473207468656044820152691036b0bc1039b2b6361760b11b60648201526084016200020f565b6001600160a01b03821660009081526036602052604090205460ff1662000b24576026546001600160a01b03831660009081526020819052604090205462000ade90836200176f565b111562000b245760405162461bcd60e51b815260206004820152601360248201527213585e0815d85b1b195d08115e18d959591959606a1b60448201526064016200020f565b306000908152602081905260409020546029548110801590819062000b515750602e5462010000900460ff165b801562000b685750602854600160a81b900460ff16155b801562000b8d57506001600160a01b03841660009081526037602052604090205460ff165b1562000bbe576028805460ff60a81b1916600160a81b17905562000bb062000e23565b6028805460ff60a81b191690555b6001600160a01b03851660009081526035602052604090205460019060ff168062000c0157506001600160a01b03851660009081526035602052604090205460ff165b1562000c0b575060005b6000811562000e0d576040805160c081018252601e548152601f546020808301919091528054828401526021546060830152602254608083015260235460a08301526001600160a01b03891660009081526037909152919091205460ff16801562000c7a575060008160a00151115b1562000d1f576103e88160a001518762000c95919062001716565b62000ca1919062001736565b91508060a0015181602001518362000cba919062001716565b62000cc6919062001736565b602f600082825462000cd991906200176f565b909155505060a0810151606082015162000cf4908462001716565b62000d00919062001736565b6030600082825462000d1391906200176f565b9091555062000de99050565b6001600160a01b03881660009081526037602052604090205460ff16801562000d4c575060008160800151115b1562000de9576103e881608001518762000d67919062001716565b62000d73919062001736565b608082015182519193509062000d8a908462001716565b62000d96919062001736565b602f600082825462000da991906200176f565b90915550506080810151604082015162000dc4908462001716565b62000dd0919062001736565b6030600082825462000de391906200176f565b90915550505b811562000dfd5762000dfd88308462000f7f565b62000e09828762001759565b9550505b62000e1a87878762000f7f565b50505050505050565b603254431462000e37574360325560006034555b60315460ff16801562000e4e575060335460345410155b1562000e5657565b3060009081526020819052604081205490506000603054602f5462000e7c91906200176f565b905081158062000e8a575080155b1562000e94575050565b60295462000ea490600f62001716565b82111562000ebf5760295462000ebc90600f62001716565b91505b600062000ecc83620010b2565b90506000606462000edf83605f62001716565b62000eeb919062001736565b905062000ef9848262001242565b602f544790600090859062000f0f908462001716565b62000f1b919062001736565b90506000602f81905550600060308190555060016034600082825462000f4291906200176f565b9091555050602a5462000f5f906001600160a01b031682620013b4565b602b5462000f77906001600160a01b031647620013b4565b505050505050565b6001600160a01b03831662000fae57806002600082825462000fa291906200176f565b90915550620010229050565b6001600160a01b03831660009081526020819052604090205481811015620010035760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016200020f565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821662001040576002805482900390556200105f565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051620010a591815260200190565b60405180910390a3505050565b604080516002808252606082018352600092839291906020830190803683370190505090503081600081518110620010ee57620010ee62001785565b60200260200101906001600160a01b031690816001600160a01b0316815250506080516001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200114f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200117591906200179b565b816001815181106200118b576200118b62001785565b6001600160a01b03928316602091820292909201015260805160405163d06ca61f60e01b8152600092919091169063d06ca61f90620011d1908790869060040162001807565b600060405180830381865afa158015620011ef573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200121991908101906200182a565b90508060018151811062001231576200123162001785565b602002602001015192505050919050565b60408051600280825260608201835260009260208301908036833701905050905030816000815181106200127a576200127a62001785565b60200260200101906001600160a01b031690816001600160a01b0316815250506080516001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015620012db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200130191906200179b565b8160018151811062001317576200131762001785565b60200260200101906001600160a01b031690816001600160a01b0316815250506200134c30608051856200145c60201b60201c565b6080516001600160a01b031663791ac94784848430426040518663ffffffff1660e01b815260040162001384959493929190620018f3565b600060405180830381600087803b1580156200139f57600080fd5b505af115801562000e1a573d6000803e3d6000fd5b80471015620013e05760405163cf47918160e01b8152476004820152602481018290526044016200020f565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146200142f576040519150601f19603f3d011682016040523d82523d6000602084013e62001434565b606091505b5050905080620014575760405163d6bda27560e01b815260040160405180910390fd5b505050565b6200145783838360016001600160a01b038416620014915760405163e602df0560e01b8152600060048201526024016200020f565b6001600160a01b038316620014bd57604051634a1406b160e11b8152600060048201526024016200020f565b6001600160a01b03808516600090815260016020908152604080832093871683529290522082905580156200153b57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516200153291815260200190565b60405180910390a35b50505050565b80516001600160a01b03811681146200155957600080fd5b919050565b600080604083850312156200157257600080fd5b6200157d8362001541565b91506200158d6020840162001541565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620015c157607f821691505b602082108103620015e257634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562001457576000816000526020600020601f850160051c81016020861015620016135750805b601f850160051c820191505b8181101562000f77578281556001016200161f565b81516001600160401b0381111562001650576200165062001596565b6200166881620016618454620015ac565b84620015e8565b602080601f831160018114620016a05760008415620016875750858301515b600019600386901b1c1916600185901b17855562000f77565b600085815260208120601f198616915b82811015620016d157888601518255948401946001909101908401620016b0565b5085821015620016f05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141762001730576200173062001700565b92915050565b6000826200175457634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111562001730576200173062001700565b8082018082111562001730576200173062001700565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620017ae57600080fd5b620017b98262001541565b9392505050565b60008151808452602080850194506020840160005b83811015620017fc5781516001600160a01b031687529582019590820190600101620017d5565b509495945050505050565b828152604060208201526000620018226040830184620017c0565b949350505050565b600060208083850312156200183e57600080fd5b82516001600160401b03808211156200185657600080fd5b818501915085601f8301126200186b57600080fd5b81518181111562001880576200188062001596565b8060051b604051601f19603f83011681018181108582111715620018a857620018a862001596565b604052918252848201925083810185019188831115620018c757600080fd5b938501935b82851015620018e757845184529385019392850192620018cc565b98975050505050505050565b85815284602082015260a0604082015260006200191460a0830186620017c0565b6001600160a01b0394909416606083015250608001529392505050565b60805160a05161377b620019d5600039600081816104a1015281816118c601528181611a600152611da50152600081816103ca0152818161156d015281816115fe015281816116ff015281816117900152818161195701528181611af101528181611c5e01528181611c8901528181611d7801528181611dce01528181611fe8015281816120a3015281816130630152818161311c0152613158015261377b6000f3fe60806040526004361061030f5760003560e01c80638366e79a11610196578063a9059cbb116100eb578063cef3f8861161008f578063e2f456051161006c578063e2f4560514610998578063ee40166e146109ae578063f2fde38b146109c4578063f8b45b05146109e457005b8063cef3f88614610918578063d86c9fec14610932578063dd62ed3e1461095257005b8063bbc0c742116100c8578063bbc0c74214610851578063bed1b47614610870578063c0246668146108c8578063c44a24dd146108e857005b8063a9059cbb146107e1578063ab968c0714610801578063b62496f51461082157005b8063906e9dd01161015257806396c58b7c1161012f57806396c58b7c146107775780639a7a23d61461078c578063a28e86d3146107ac578063a5ece941146107c157005b8063906e9dd01461072c57806395d89b411461074c578063967926691461076157005b80638366e79a1461068357806388522998146106a357806388e765ff146106c357806389dd008b146106d95780638a8c523c146106f95780638da5cb5b1461070e57005b806349bd5a5e116102645780636e55c13f1161020857806373d01ead116101e557806373d01ead14610619578063751039fc1461062e5780637571336a146106435780637da9dd461461066357005b80636e55c13f146105c457806370a08231146105e4578063715018a61461060457005b806357bd8bb31161024157806357bd8bb31461054e57806366d602ae1461056e578063672fc7be146105845780636ddd1713146105a457005b806349bd5a5e146104f45780634a62bb65146105145780634be813e61461052e57005b80631f3fed8f116102cb57806324b9f3c1116102a857806324b9f3c1146104795780632c76d7a61461048f578063313ce567146104c357806331cd1eeb146104df57005b80631f3fed8f1461042357806322713e6b1461043957806323b872dd1461045957005b80630614117a1461031857806306fdde031461032d578063095ea7b31461035857806310d5de53146103885780631694505e146103b857806318160ddd1461040457005b3661031657005b005b34801561032457600080fd5b506103166109fa565b34801561033957600080fd5b50610342610a9c565b60405161034f9190613261565b60405180910390f35b34801561036457600080fd5b506103786103733660046132c5565b610b2e565b604051901515815260200161034f565b34801561039457600080fd5b506103786103a33660046132f1565b60366020526000908152604090205460ff1681565b3480156103c457600080fd5b506103ec7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161034f565b34801561041057600080fd5b506002545b60405190815260200161034f565b34801561042f57600080fd5b5061041560305481565b34801561044557600080fd5b50610316610454366004613315565b610b48565b34801561046557600080fd5b50610378610474366004613338565b610cd2565b34801561048557600080fd5b50610415602f5481565b34801561049b57600080fd5b506103ec7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104cf57600080fd5b506040516012815260200161034f565b3480156104eb57600080fd5b50610316610cf6565b34801561050057600080fd5b506027546103ec906001600160a01b031681565b34801561052057600080fd5b50602e546103789060ff1681565b34801561053a57600080fd5b50610316610549366004613379565b610d79565b34801561055a57600080fd5b506103166105693660046132f1565b610dee565b34801561057a57600080fd5b5061041560255481565b34801561059057600080fd5b5061031661059f366004613403565b610e83565b3480156105b057600080fd5b50602e546103789062010000900460ff1681565b3480156105d057600080fd5b506103166105df366004613379565b610f05565b3480156105f057600080fd5b506104156105ff3660046132f1565b610f75565b34801561061057600080fd5b50610316610f90565b34801561062557600080fd5b50610316610fa4565b34801561063a57600080fd5b50610316611016565b34801561064f57600080fd5b5061031661065e36600461341f565b61102a565b34801561066f57600080fd5b50602a546103ec906001600160a01b031681565b34801561068f57600080fd5b5061037861069e366004613454565b6110d0565b3480156106af57600080fd5b506028546103ec906001600160a01b031681565b3480156106cf57600080fd5b5061041560245481565b3480156106e557600080fd5b506103166106f43660046132f1565b6112dc565b34801561070557600080fd5b50610316611390565b34801561071a57600080fd5b506005546001600160a01b03166103ec565b34801561073857600080fd5b506103166107473660046132f1565b611430565b34801561075857600080fd5b506103426114e6565b34801561076d57600080fd5b5061041560335481565b34801561078357600080fd5b506103166114f5565b34801561079857600080fd5b506103166107a736600461341f565b611e96565b3480156107b857600080fd5b50610316611f68565b3480156107cd57600080fd5b50602b546103ec906001600160a01b031681565b3480156107ed57600080fd5b506103786107fc3660046132c5565b611f7f565b34801561080d57600080fd5b5061041561081c36600461348d565b611f8d565b34801561082d57600080fd5b5061037861083c3660046132f1565b60376020526000908152604090205460ff1681565b34801561085d57600080fd5b50602e5461037890610100900460ff1681565b34801561087c57600080fd5b50601e54601f5460205460215460225460235461089b95949392919086565b604080519687526020870195909552938501929092526060840152608083015260a082015260c00161034f565b3480156108d457600080fd5b506103166108e336600461341f565b612145565b3480156108f457600080fd5b506103786109033660046132f1565b602d6020526000908152604090205460ff1681565b34801561092457600080fd5b506031546103789060ff1681565b34801561093e57600080fd5b5061031661094d3660046132f1565b6121ac565b34801561095e57600080fd5b5061041561096d366004613454565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3480156109a457600080fd5b5061041560295481565b3480156109ba57600080fd5b50610415602c5481565b3480156109d057600080fd5b506103166109df3660046132f1565b61223d565b3480156109f057600080fd5b5061041560265481565b610a02612278565b604051600090339047908381818185875af1925050503d8060008114610a44576040519150601f19603f3d011682016040523d82523d6000602084013e610a49565b606091505b50508091505080610a995760405162461bcd60e51b815260206004820152601560248201527408cc2d2d8cac840e8de40e4cac6deeccae4408aa89605b1b60448201526064015b60405180910390fd5b50565b606060038054610aab906134a6565b80601f0160208091040260200160405190810160405280929190818152602001828054610ad7906134a6565b8015610b245780601f10610af957610100808354040283529160200191610b24565b820191906000526020600020905b815481529060010190602001808311610b0757829003601f168201915b5050505050905090565b600033610b3c8185856122a5565b60019150505b92915050565b610b50612278565b60008160ff16118015610b67575060048160ff1611155b610bcd5760405162461bcd60e51b815260206004820152603160248201527f496e76616c696420546178205374727563747572653a2056616c7565206d75736044820152701d081899480c4b080c8b080cc81bdc880d607a1b6064820152608401610a90565b8060ff16600103610c0157600654601e55600754601f55600854602055600954602155600a54602255600b54602355610c99565b8060ff16600203610c3557600c54601e55600d54601f55600e54602055600f54602155601054602255601154602355610c99565b8060ff16600303610c6957601254601e55601354601f55601454602055601554602155601654602255601754602355610c99565b8060ff16600403610c9957601854601e55601954601f55601a54602055601b54602155601c54602255601d546023555b60405160ff821681527f17b99fbbda41ba2294a55c9a9d262bc581dcf86eb7d7efe6fe1dee15a3a6c2509060200160405180910390a150565b600033610ce08582856122b2565b610ceb858585612330565b506001949350505050565b610cfe612278565b602854600160a01b900460ff16610d6a5760405162461bcd60e51b815260206004820152602a60248201527f5633204c502050726f74656374696f6e20616c72656164792064697361626c656044820152696420666f72657665722160b01b6064820152608401610a90565b6028805460ff60a01b19169055565b610d81612278565b60005b81811015610de9576000602d6000858585818110610da457610da46134e0565b9050602002016020810190610db991906132f1565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101610d84565b505050565b610df6612278565b6001600160a01b0381166000908152602d602052604090205460ff1615610e5f5760405162461bcd60e51b815260206004820152601a60248201527f57616c6c657420697320616c726561647920666c61676765642e0000000000006044820152606401610a90565b6001600160a01b03166000908152602d60205260409020805460ff19166001179055565b610e8b612278565b60008111610eee5760405162461bcd60e51b815260206004820152602a60248201527f4d61782073776170732070657220626c6f636b206d75737420626520677265616044820152690746572207468616e20360b41b6064820152608401610a90565b6031805460ff191692151592909217909155603355565b610f0d612278565b60005b81811015610de9576001602d6000858585818110610f3057610f306134e0565b9050602002016020810190610f4591906132f1565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101610f10565b6001600160a01b031660009081526020819052604090205490565b610f98612278565b610fa2600061238f565b565b610fac612278565b602e805460ff19169055600254602955601854601e55601954601f55601a54602055601b54602155601c54602255601d546023556002546024556002546025556002546026556000610ffd30610f75565b1115610fa257610fa2303361101130610f75565b6123e1565b61101e612278565b602e805460ff19169055565b611032612278565b806110a5576027546001600160a01b03908116908316036110a55760405162461bcd60e51b815260206004820152602760248201527f43616e6e6f742072656d6f766520756e697377617020706169722066726f6d2060448201526636b0bc103a3c3760c91b6064820152608401610a90565b6001600160a01b03919091166000908152603660205260409020805460ff1916911515919091179055565b60006110da612278565b6001600160a01b0383166111305760405162461bcd60e51b815260206004820152601a60248201527f5f746f6b656e20616464726573732063616e6e6f7420626520300000000000006044820152606401610a90565b6001600160a01b0382166111865760405162461bcd60e51b815260206004820152601760248201527f5f746f20616464726573732063616e6e6f7420626520300000000000000000006044820152606401610a90565b6001600160a01b038316301415806111a65750602e54610100900460ff16155b61120f5760405162461bcd60e51b815260206004820152603460248201527f43616e2774207769746864726177206e617469766520746f6b656e73207768696044820152736c652074726164696e672069732061637469766560601b6064820152608401610a90565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a91906134f6565b90506112906001600160a01b038516848361250b565b604080516001600160a01b0386168152602081018390527fdeda980967fcead7b61e78ac46a4da14274af29e894d4d61e8b81ec38ab3e438910160405180910390a15060019392505050565b6112e4612278565b6001600160a01b0381166113465760405162461bcd60e51b8152602060048201526024808201527f5f72657653686172654164647265737320616464726573732063616e6e6f74206044820152630626520360e41b6064820152608401610a90565b602a80546001600160a01b0319166001600160a01b0383169081179091556040517fdd96ec66795ecb2d5751a192ff46ec766fab6e34eb865b99648cd72a7c9151fd90600090a250565b611398612278565b602e54610100900460ff16156113f05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207265656e61626c652074726164696e670000000000000000006044820152606401610a90565b602e805462ffff0019166201010017905543602c556040517fa56feb2d31b9a7424db0be063fd450863979c9e2382cf5110f869bd1ad361bb790600090a1565b611438612278565b6001600160a01b03811661149c5760405162461bcd60e51b815260206004820152602560248201527f5f6d61726b6574696e674164647265737320616464726573732063616e6e6f74604482015264020626520360dc1b6064820152608401610a90565b602b80546001600160a01b0319166001600160a01b0383169081179091556040517fd1e7d6a3390dd5008bd1c57798817b9f806e4c417264e7d3d67e42e784dc24a990600090a250565b606060048054610aab906134a6565b6114fd612278565b602e54610100900460ff16156115695760405162461bcd60e51b815260206004820152602b60248201527f54726164696e6720697320616c7265616479206163746976652c2063616e6e6f60448201526a3a103932b630bab731b41760a91b6064820152608401610a90565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ed919061350f565b6001600160a01b031663e6a43905307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa15801561165a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167e919061350f565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa1580156116c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ed919061350f565b90506001600160a01b0381166118a6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561175b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177f919061350f565b6001600160a01b031663c9c65396307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611810919061350f565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af115801561185d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611881919061350f565b602780546001600160a01b0319166001600160a01b03929092169190911790556118c2565b602780546001600160a01b0319166001600160a01b0383161790555b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611946919061350f565b6001600160a01b0316631698ee82307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d7919061350f565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526127106044820152606401602060405180830381865afa158015611a2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4e919061350f565b90506001600160a01b038116611c0f577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611abc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae0919061350f565b6001600160a01b031663a1671295307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b71919061350f565b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015261271060448201526064016020604051808303816000875af1158015611bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bea919061350f565b602880546001600160a01b0319166001600160a01b0392909216919091179055611c2b565b602880546001600160a01b0319166001600160a01b0383161790555b602754611c42906001600160a01b0316600161255d565b602754611c59906001600160a01b031660016125c0565b611c847f0000000000000000000000000000000000000000000000000000000000000000600161255d565b611caf7f00000000000000000000000000000000000000000000000000000000000000006001612145565b60004711611d0b5760405162461bcd60e51b815260206004820152602360248201527f4d757374206861766520455448206f6e20636f6e747261637420746f206c61756044820152620dcc6d60eb1b6064820152608401610a90565b6000611d1630610f75565b11611d725760405162461bcd60e51b815260206004820152602660248201527f4d757374206861766520546f6b656e73206f6e20636f6e747261637420746f206044820152650d8c2eadcc6d60d31b6064820152608401610a90565b611d9f307f00000000000000000000000000000000000000000000000000000000000000006000196122a5565b611dcc307f00000000000000000000000000000000000000000000000000000000000000006000196122a5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f305d7194730611e0630610f75565b6040516001600160e01b031960e086901b1681526001600160a01b039092166004830152602482015260006044820181905260648201523360848201524260a482015260c40160606040518083038185885af1158015611e6a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e8f919061352c565b5050505050565b611e9e612278565b6027546001600160a01b0390811690831603611f225760405162461bcd60e51b815260206004820152603960248201527f54686520706169722063616e6e6f742062652072656d6f7665642066726f6d2060448201527f6175746f6d617465644d61726b65744d616b65725061697273000000000000006064820152608401610a90565b611f2c82826125c0565b604051811515906001600160a01b038416907fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab90600090a35050565b611f70612278565b602e805460ff19166001179055565b600033610b3c818585612330565b604080516002808252606082018352600092839291906020830190803683370190505090503081600081518110611fc657611fc66134e0565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612068919061350f565b8160018151811061207b5761207b6134e0565b6001600160a01b03928316602091820292909201015260405163d06ca61f60e01b81526000917f0000000000000000000000000000000000000000000000000000000000000000169063d06ca61f906120da90879086906004016135b5565b600060405180830381865afa1580156120f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261211f91908101906135d6565b905080600181518110612134576121346134e0565b602002602001015192505050919050565b61214d612278565b6001600160a01b038216600081815260356020908152604091829020805460ff191685151590811790915591519182527f9d8f7706ea1113d1a167b526eca956215946dd36cc7df39eb16180222d8b5df7910160405180910390a25050565b6121b4612278565b6001600160a01b0381166000908152602d602052604090205460ff1661221c5760405162461bcd60e51b815260206004820152601d60248201527f57616c6c657420697320616c7265616479206e6f74206d61726b65642e0000006044820152606401610a90565b6001600160a01b03166000908152602d60205260409020805460ff19169055565b612245612278565b6001600160a01b03811661226f57604051631e4fbdf760e01b815260006004820152602401610a90565b610a998161238f565b6005546001600160a01b03163314610fa25760405163118cdaa760e01b8152336004820152602401610a90565b610de983838360016125ee565b6001600160a01b03838116600090815260016020908152604080832093861683529290522054600019811461232a578181101561231b57604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610a90565b61232a848484840360006125ee565b50505050565b6001600160a01b03831661235a57604051634b637e8f60e11b815260006004820152602401610a90565b6001600160a01b0382166123845760405163ec442f0560e01b815260006004820152602401610a90565b610de98383836126c3565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03831661240c57806002600082825461240191906136aa565b9091555061247e9050565b6001600160a01b0383166000908152602081905260409020548181101561245f5760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610a90565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821661249a576002805482900390556124b9565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516124fe91815260200190565b60405180910390a3505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610de9908490612e62565b6001600160a01b038216600081815260366020908152604091829020805460ff19168515159081179091558251938452908301527f6b4f1be9103e6cbcd38ca4a922334f2c3109b260130a6676a987f94088fd6746910160405180910390a15050565b6001600160a01b0382166000908152603760205260409020805460ff1916821515179055611f2c828261255d565b6001600160a01b0384166126185760405163e602df0560e01b815260006004820152602401610a90565b6001600160a01b03831661264257604051634a1406b160e11b815260006004820152602401610a90565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561232a57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516126b591815260200190565b60405180910390a350505050565b600081116127135760405162461bcd60e51b815260206004820152601d60248201527f616d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610a90565b602e54610100900460ff166127ab576001600160a01b03831660009081526035602052604090205460ff168061276157506001600160a01b03821660009081526035602052604090205460ff165b6127a65760405162461bcd60e51b81526020600482015260166024820152752a3930b234b7339034b9903737ba1030b1ba34bb329760511b6044820152606401610a90565b612814565b6001600160a01b0383166000908152602d602052604090205460ff16156128145760405162461bcd60e51b815260206004820152601e60248201527f536e69706572732063616e6e6f74207472616e7366657220746f6b656e7300006044820152606401610a90565b602854600160a01b900460ff1615612904576001600160a01b03831660009081526035602052604090205460ff1615801561286857506001600160a01b03821660009081526035602052604090205460ff16155b15612904576028546001600160a01b0384811691161480159061289957506028546001600160a01b03838116911614155b6129045760405162461bcd60e51b815260206004820152603660248201527f563320506f6f6c2069732063757272656e746c792070726f7465637465642c206044820152751d1c985b9cd9995c9cc8185c9948191a5cd8589b195960521b6064820152608401610a90565b602e5460ff1615612b9a576001600160a01b03821661dead1480159061294357506001600160a01b03831660009081526035602052604090205460ff16155b801561296857506001600160a01b03821660009081526035602052604090205460ff16155b15612b9a576001600160a01b03831660009081526037602052604090205460ff1680156129ae57506001600160a01b03821660009081526036602052604090205460ff16155b15612a7557602454811115612a165760405162461bcd60e51b815260206004820152602860248201527f427579207472616e7366657220616d6f756e742065786365656473207468652060448201526736b0bc10313abc9760c11b6064820152608401610a90565b602654612a2283610f75565b612a2c90836136aa565b1115612a705760405162461bcd60e51b815260206004820152601360248201527213585e0815d85b1b195d08115e18d959591959606a1b6044820152606401610a90565b612b9a565b6001600160a01b03821660009081526037602052604090205460ff168015612ab657506001600160a01b03831660009081526036602052604090205460ff16155b15612b2057602554811115612a705760405162461bcd60e51b815260206004820152602a60248201527f53656c6c207472616e7366657220616d6f756e742065786365656473207468656044820152691036b0bc1039b2b6361760b11b6064820152608401610a90565b6001600160a01b03821660009081526036602052604090205460ff16612b9a57602654612b4c83610f75565b612b5690836136aa565b1115612b9a5760405162461bcd60e51b815260206004820152601360248201527213585e0815d85b1b195d08115e18d959591959606a1b6044820152606401610a90565b6000612ba530610f75565b60295490915081108015908190612bc45750602e5462010000900460ff165b8015612bda5750602854600160a81b900460ff16155b8015612bfe57506001600160a01b03841660009081526037602052604090205460ff165b15612c2c576028805460ff60a81b1916600160a81b179055612c1e612ed3565b6028805460ff60a81b191690555b6001600160a01b03851660009081526035602052604090205460019060ff1680612c6e57506001600160a01b03851660009081526035602052604090205460ff165b15612c77575060005b60008115612e4e576040805160c081018252601e548152601f546020808301919091528054828401526021546060830152602254608083015260235460a08301526001600160a01b03891660009081526037909152919091205460ff168015612ce4575060008160a00151115b15612d77576103e88160a0015187612cfc91906136bd565b612d0691906136d4565b91508060a00151816020015183612d1d91906136bd565b612d2791906136d4565b602f6000828254612d3891906136aa565b909155505060a08101516060820151612d5190846136bd565b612d5b91906136d4565b60306000828254612d6c91906136aa565b90915550612e2f9050565b6001600160a01b03881660009081526037602052604090205460ff168015612da3575060008160800151115b15612e2f576103e8816080015187612dbb91906136bd565b612dc591906136d4565b6080820151825191935090612dda90846136bd565b612de491906136d4565b602f6000828254612df591906136aa565b909155505060808101516040820151612e0e90846136bd565b612e1891906136d4565b60306000828254612e2991906136aa565b90915550505b8115612e4057612e408830846123e1565b612e4a82876136f6565b9550505b612e598787876123e1565b50505050505050565b600080602060008451602086016000885af180612e85576040513d6000823e3d81fd5b50506000513d91508115612e9d578060011415612eaa565b6001600160a01b0384163b155b1561232a57604051635274afe760e01b81526001600160a01b0385166004820152602401610a90565b6032544314612ee6574360325560006034555b60315460ff168015612efc575060335460345410155b15612f0357565b6000612f0e30610f75565b90506000603054602f54612f2291906136aa565b9050811580612f2f575080155b15612f38575050565b602954612f4690600f6136bd565b821115612f5e57602954612f5b90600f6136bd565b91505b6000612f6983611f8d565b905060006064612f7a83605f6136bd565b612f8491906136d4565b9050612f90848261300c565b602f5447906000908590612fa490846136bd565b612fae91906136d4565b90506000602f819055506000603081905550600160346000828254612fd391906136aa565b9091555050602a54612fee906001600160a01b0316826131c3565b602b54613004906001600160a01b0316476131c3565b505050505050565b6040805160028082526060820183526000926020830190803683370190505090503081600081518110613041576130416134e0565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e3919061350f565b816001815181106130f6576130f66134e0565b60200260200101906001600160a01b031690816001600160a01b031681525050613141307f0000000000000000000000000000000000000000000000000000000000000000856122a5565b60405163791ac94760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063791ac947906131959086908690869030904290600401613709565b600060405180830381600087803b1580156131af57600080fd5b505af1158015612e59573d6000803e3d6000fd5b804710156131ed5760405163cf47918160e01b815247600482015260248101829052604401610a90565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461323a576040519150601f19603f3d011682016040523d82523d6000602084013e61323f565b606091505b5050905080610de95760405163d6bda27560e01b815260040160405180910390fd5b60006020808352835180602085015260005b8181101561328f57858101830151858201604001528201613273565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b0381168114610a9957600080fd5b600080604083850312156132d857600080fd5b82356132e3816132b0565b946020939093013593505050565b60006020828403121561330357600080fd5b813561330e816132b0565b9392505050565b60006020828403121561332757600080fd5b813560ff8116811461330e57600080fd5b60008060006060848603121561334d57600080fd5b8335613358816132b0565b92506020840135613368816132b0565b929592945050506040919091013590565b6000806020838503121561338c57600080fd5b823567ffffffffffffffff808211156133a457600080fd5b818501915085601f8301126133b857600080fd5b8135818111156133c757600080fd5b8660208260051b85010111156133dc57600080fd5b60209290920196919550909350505050565b803580151581146133fe57600080fd5b919050565b6000806040838503121561341657600080fd5b6132e3836133ee565b6000806040838503121561343257600080fd5b823561343d816132b0565b915061344b602084016133ee565b90509250929050565b6000806040838503121561346757600080fd5b8235613472816132b0565b91506020830135613482816132b0565b809150509250929050565b60006020828403121561349f57600080fd5b5035919050565b600181811c908216806134ba57607f821691505b6020821081036134da57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561350857600080fd5b5051919050565b60006020828403121561352157600080fd5b815161330e816132b0565b60008060006060848603121561354157600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052604160045260246000fd5b60008151808452602080850194506020840160005b838110156135aa5781516001600160a01b031687529582019590820190600101613585565b509495945050505050565b8281526040602082015260006135ce6040830184613570565b949350505050565b600060208083850312156135e957600080fd5b825167ffffffffffffffff8082111561360157600080fd5b818501915085601f83011261361557600080fd5b8151818111156136275761362761355a565b8060051b604051601f19603f8301168101818110858211171561364c5761364c61355a565b60405291825284820192508381018501918883111561366a57600080fd5b938501935b828510156136885784518452938501939285019261366f565b98975050505050505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610b4257610b42613694565b8082028115828204841417610b4257610b42613694565b6000826136f157634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610b4257610b42613694565b85815284602082015260a06040820152600061372860a0830186613570565b6001600160a01b039490941660608301525060800152939250505056fea2646970667358221220563d9bb65f5afc119dd277abe25694c6874f669e2f8cc2c1200e920a3c7e5a7364736f6c63430008170033000000000000000000000000ca91a5cb5edba36cd4cee8872035233516c6b1d7000000000000000000000000ef78e11c9a31154753297ee4a196dfce071f16bd

Deployed Bytecode

0x60806040526004361061030f5760003560e01c80638366e79a11610196578063a9059cbb116100eb578063cef3f8861161008f578063e2f456051161006c578063e2f4560514610998578063ee40166e146109ae578063f2fde38b146109c4578063f8b45b05146109e457005b8063cef3f88614610918578063d86c9fec14610932578063dd62ed3e1461095257005b8063bbc0c742116100c8578063bbc0c74214610851578063bed1b47614610870578063c0246668146108c8578063c44a24dd146108e857005b8063a9059cbb146107e1578063ab968c0714610801578063b62496f51461082157005b8063906e9dd01161015257806396c58b7c1161012f57806396c58b7c146107775780639a7a23d61461078c578063a28e86d3146107ac578063a5ece941146107c157005b8063906e9dd01461072c57806395d89b411461074c578063967926691461076157005b80638366e79a1461068357806388522998146106a357806388e765ff146106c357806389dd008b146106d95780638a8c523c146106f95780638da5cb5b1461070e57005b806349bd5a5e116102645780636e55c13f1161020857806373d01ead116101e557806373d01ead14610619578063751039fc1461062e5780637571336a146106435780637da9dd461461066357005b80636e55c13f146105c457806370a08231146105e4578063715018a61461060457005b806357bd8bb31161024157806357bd8bb31461054e57806366d602ae1461056e578063672fc7be146105845780636ddd1713146105a457005b806349bd5a5e146104f45780634a62bb65146105145780634be813e61461052e57005b80631f3fed8f116102cb57806324b9f3c1116102a857806324b9f3c1146104795780632c76d7a61461048f578063313ce567146104c357806331cd1eeb146104df57005b80631f3fed8f1461042357806322713e6b1461043957806323b872dd1461045957005b80630614117a1461031857806306fdde031461032d578063095ea7b31461035857806310d5de53146103885780631694505e146103b857806318160ddd1461040457005b3661031657005b005b34801561032457600080fd5b506103166109fa565b34801561033957600080fd5b50610342610a9c565b60405161034f9190613261565b60405180910390f35b34801561036457600080fd5b506103786103733660046132c5565b610b2e565b604051901515815260200161034f565b34801561039457600080fd5b506103786103a33660046132f1565b60366020526000908152604090205460ff1681565b3480156103c457600080fd5b506103ec7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81565b6040516001600160a01b03909116815260200161034f565b34801561041057600080fd5b506002545b60405190815260200161034f565b34801561042f57600080fd5b5061041560305481565b34801561044557600080fd5b50610316610454366004613315565b610b48565b34801561046557600080fd5b50610378610474366004613338565b610cd2565b34801561048557600080fd5b50610415602f5481565b34801561049b57600080fd5b506103ec7f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b3480156104cf57600080fd5b506040516012815260200161034f565b3480156104eb57600080fd5b50610316610cf6565b34801561050057600080fd5b506027546103ec906001600160a01b031681565b34801561052057600080fd5b50602e546103789060ff1681565b34801561053a57600080fd5b50610316610549366004613379565b610d79565b34801561055a57600080fd5b506103166105693660046132f1565b610dee565b34801561057a57600080fd5b5061041560255481565b34801561059057600080fd5b5061031661059f366004613403565b610e83565b3480156105b057600080fd5b50602e546103789062010000900460ff1681565b3480156105d057600080fd5b506103166105df366004613379565b610f05565b3480156105f057600080fd5b506104156105ff3660046132f1565b610f75565b34801561061057600080fd5b50610316610f90565b34801561062557600080fd5b50610316610fa4565b34801561063a57600080fd5b50610316611016565b34801561064f57600080fd5b5061031661065e36600461341f565b61102a565b34801561066f57600080fd5b50602a546103ec906001600160a01b031681565b34801561068f57600080fd5b5061037861069e366004613454565b6110d0565b3480156106af57600080fd5b506028546103ec906001600160a01b031681565b3480156106cf57600080fd5b5061041560245481565b3480156106e557600080fd5b506103166106f43660046132f1565b6112dc565b34801561070557600080fd5b50610316611390565b34801561071a57600080fd5b506005546001600160a01b03166103ec565b34801561073857600080fd5b506103166107473660046132f1565b611430565b34801561075857600080fd5b506103426114e6565b34801561076d57600080fd5b5061041560335481565b34801561078357600080fd5b506103166114f5565b34801561079857600080fd5b506103166107a736600461341f565b611e96565b3480156107b857600080fd5b50610316611f68565b3480156107cd57600080fd5b50602b546103ec906001600160a01b031681565b3480156107ed57600080fd5b506103786107fc3660046132c5565b611f7f565b34801561080d57600080fd5b5061041561081c36600461348d565b611f8d565b34801561082d57600080fd5b5061037861083c3660046132f1565b60376020526000908152604090205460ff1681565b34801561085d57600080fd5b50602e5461037890610100900460ff1681565b34801561087c57600080fd5b50601e54601f5460205460215460225460235461089b95949392919086565b604080519687526020870195909552938501929092526060840152608083015260a082015260c00161034f565b3480156108d457600080fd5b506103166108e336600461341f565b612145565b3480156108f457600080fd5b506103786109033660046132f1565b602d6020526000908152604090205460ff1681565b34801561092457600080fd5b506031546103789060ff1681565b34801561093e57600080fd5b5061031661094d3660046132f1565b6121ac565b34801561095e57600080fd5b5061041561096d366004613454565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3480156109a457600080fd5b5061041560295481565b3480156109ba57600080fd5b50610415602c5481565b3480156109d057600080fd5b506103166109df3660046132f1565b61223d565b3480156109f057600080fd5b5061041560265481565b610a02612278565b604051600090339047908381818185875af1925050503d8060008114610a44576040519150601f19603f3d011682016040523d82523d6000602084013e610a49565b606091505b50508091505080610a995760405162461bcd60e51b815260206004820152601560248201527408cc2d2d8cac840e8de40e4cac6deeccae4408aa89605b1b60448201526064015b60405180910390fd5b50565b606060038054610aab906134a6565b80601f0160208091040260200160405190810160405280929190818152602001828054610ad7906134a6565b8015610b245780601f10610af957610100808354040283529160200191610b24565b820191906000526020600020905b815481529060010190602001808311610b0757829003601f168201915b5050505050905090565b600033610b3c8185856122a5565b60019150505b92915050565b610b50612278565b60008160ff16118015610b67575060048160ff1611155b610bcd5760405162461bcd60e51b815260206004820152603160248201527f496e76616c696420546178205374727563747572653a2056616c7565206d75736044820152701d081899480c4b080c8b080cc81bdc880d607a1b6064820152608401610a90565b8060ff16600103610c0157600654601e55600754601f55600854602055600954602155600a54602255600b54602355610c99565b8060ff16600203610c3557600c54601e55600d54601f55600e54602055600f54602155601054602255601154602355610c99565b8060ff16600303610c6957601254601e55601354601f55601454602055601554602155601654602255601754602355610c99565b8060ff16600403610c9957601854601e55601954601f55601a54602055601b54602155601c54602255601d546023555b60405160ff821681527f17b99fbbda41ba2294a55c9a9d262bc581dcf86eb7d7efe6fe1dee15a3a6c2509060200160405180910390a150565b600033610ce08582856122b2565b610ceb858585612330565b506001949350505050565b610cfe612278565b602854600160a01b900460ff16610d6a5760405162461bcd60e51b815260206004820152602a60248201527f5633204c502050726f74656374696f6e20616c72656164792064697361626c656044820152696420666f72657665722160b01b6064820152608401610a90565b6028805460ff60a01b19169055565b610d81612278565b60005b81811015610de9576000602d6000858585818110610da457610da46134e0565b9050602002016020810190610db991906132f1565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101610d84565b505050565b610df6612278565b6001600160a01b0381166000908152602d602052604090205460ff1615610e5f5760405162461bcd60e51b815260206004820152601a60248201527f57616c6c657420697320616c726561647920666c61676765642e0000000000006044820152606401610a90565b6001600160a01b03166000908152602d60205260409020805460ff19166001179055565b610e8b612278565b60008111610eee5760405162461bcd60e51b815260206004820152602a60248201527f4d61782073776170732070657220626c6f636b206d75737420626520677265616044820152690746572207468616e20360b41b6064820152608401610a90565b6031805460ff191692151592909217909155603355565b610f0d612278565b60005b81811015610de9576001602d6000858585818110610f3057610f306134e0565b9050602002016020810190610f4591906132f1565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101610f10565b6001600160a01b031660009081526020819052604090205490565b610f98612278565b610fa2600061238f565b565b610fac612278565b602e805460ff19169055600254602955601854601e55601954601f55601a54602055601b54602155601c54602255601d546023556002546024556002546025556002546026556000610ffd30610f75565b1115610fa257610fa2303361101130610f75565b6123e1565b61101e612278565b602e805460ff19169055565b611032612278565b806110a5576027546001600160a01b03908116908316036110a55760405162461bcd60e51b815260206004820152602760248201527f43616e6e6f742072656d6f766520756e697377617020706169722066726f6d2060448201526636b0bc103a3c3760c91b6064820152608401610a90565b6001600160a01b03919091166000908152603660205260409020805460ff1916911515919091179055565b60006110da612278565b6001600160a01b0383166111305760405162461bcd60e51b815260206004820152601a60248201527f5f746f6b656e20616464726573732063616e6e6f7420626520300000000000006044820152606401610a90565b6001600160a01b0382166111865760405162461bcd60e51b815260206004820152601760248201527f5f746f20616464726573732063616e6e6f7420626520300000000000000000006044820152606401610a90565b6001600160a01b038316301415806111a65750602e54610100900460ff16155b61120f5760405162461bcd60e51b815260206004820152603460248201527f43616e2774207769746864726177206e617469766520746f6b656e73207768696044820152736c652074726164696e672069732061637469766560601b6064820152608401610a90565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127a91906134f6565b90506112906001600160a01b038516848361250b565b604080516001600160a01b0386168152602081018390527fdeda980967fcead7b61e78ac46a4da14274af29e894d4d61e8b81ec38ab3e438910160405180910390a15060019392505050565b6112e4612278565b6001600160a01b0381166113465760405162461bcd60e51b8152602060048201526024808201527f5f72657653686172654164647265737320616464726573732063616e6e6f74206044820152630626520360e41b6064820152608401610a90565b602a80546001600160a01b0319166001600160a01b0383169081179091556040517fdd96ec66795ecb2d5751a192ff46ec766fab6e34eb865b99648cd72a7c9151fd90600090a250565b611398612278565b602e54610100900460ff16156113f05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207265656e61626c652074726164696e670000000000000000006044820152606401610a90565b602e805462ffff0019166201010017905543602c556040517fa56feb2d31b9a7424db0be063fd450863979c9e2382cf5110f869bd1ad361bb790600090a1565b611438612278565b6001600160a01b03811661149c5760405162461bcd60e51b815260206004820152602560248201527f5f6d61726b6574696e674164647265737320616464726573732063616e6e6f74604482015264020626520360dc1b6064820152608401610a90565b602b80546001600160a01b0319166001600160a01b0383169081179091556040517fd1e7d6a3390dd5008bd1c57798817b9f806e4c417264e7d3d67e42e784dc24a990600090a250565b606060048054610aab906134a6565b6114fd612278565b602e54610100900460ff16156115695760405162461bcd60e51b815260206004820152602b60248201527f54726164696e6720697320616c7265616479206163746976652c2063616e6e6f60448201526a3a103932b630bab731b41760a91b6064820152608401610a90565b60007f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ed919061350f565b6001600160a01b031663e6a43905307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa15801561165a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167e919061350f565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa1580156116c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ed919061350f565b90506001600160a01b0381166118a6577f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561175b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177f919061350f565b6001600160a01b031663c9c65396307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611810919061350f565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af115801561185d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611881919061350f565b602780546001600160a01b0319166001600160a01b03929092169190911790556118c2565b602780546001600160a01b0319166001600160a01b0383161790555b60007f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611946919061350f565b6001600160a01b0316631698ee82307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d7919061350f565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526127106044820152606401602060405180830381865afa158015611a2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4e919061350f565b90506001600160a01b038116611c0f577f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611abc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae0919061350f565b6001600160a01b031663a1671295307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b71919061350f565b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015261271060448201526064016020604051808303816000875af1158015611bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bea919061350f565b602880546001600160a01b0319166001600160a01b0392909216919091179055611c2b565b602880546001600160a01b0319166001600160a01b0383161790555b602754611c42906001600160a01b0316600161255d565b602754611c59906001600160a01b031660016125c0565b611c847f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d600161255d565b611caf7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001612145565b60004711611d0b5760405162461bcd60e51b815260206004820152602360248201527f4d757374206861766520455448206f6e20636f6e747261637420746f206c61756044820152620dcc6d60eb1b6064820152608401610a90565b6000611d1630610f75565b11611d725760405162461bcd60e51b815260206004820152602660248201527f4d757374206861766520546f6b656e73206f6e20636f6e747261637420746f206044820152650d8c2eadcc6d60d31b6064820152608401610a90565b611d9f307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6000196122a5565b611dcc307f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646000196122a5565b7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663f305d7194730611e0630610f75565b6040516001600160e01b031960e086901b1681526001600160a01b039092166004830152602482015260006044820181905260648201523360848201524260a482015260c40160606040518083038185885af1158015611e6a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e8f919061352c565b5050505050565b611e9e612278565b6027546001600160a01b0390811690831603611f225760405162461bcd60e51b815260206004820152603960248201527f54686520706169722063616e6e6f742062652072656d6f7665642066726f6d2060448201527f6175746f6d617465644d61726b65744d616b65725061697273000000000000006064820152608401610a90565b611f2c82826125c0565b604051811515906001600160a01b038416907fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab90600090a35050565b611f70612278565b602e805460ff19166001179055565b600033610b3c818585612330565b604080516002808252606082018352600092839291906020830190803683370190505090503081600081518110611fc657611fc66134e0565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612068919061350f565b8160018151811061207b5761207b6134e0565b6001600160a01b03928316602091820292909201015260405163d06ca61f60e01b81526000917f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d169063d06ca61f906120da90879086906004016135b5565b600060405180830381865afa1580156120f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261211f91908101906135d6565b905080600181518110612134576121346134e0565b602002602001015192505050919050565b61214d612278565b6001600160a01b038216600081815260356020908152604091829020805460ff191685151590811790915591519182527f9d8f7706ea1113d1a167b526eca956215946dd36cc7df39eb16180222d8b5df7910160405180910390a25050565b6121b4612278565b6001600160a01b0381166000908152602d602052604090205460ff1661221c5760405162461bcd60e51b815260206004820152601d60248201527f57616c6c657420697320616c7265616479206e6f74206d61726b65642e0000006044820152606401610a90565b6001600160a01b03166000908152602d60205260409020805460ff19169055565b612245612278565b6001600160a01b03811661226f57604051631e4fbdf760e01b815260006004820152602401610a90565b610a998161238f565b6005546001600160a01b03163314610fa25760405163118cdaa760e01b8152336004820152602401610a90565b610de983838360016125ee565b6001600160a01b03838116600090815260016020908152604080832093861683529290522054600019811461232a578181101561231b57604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610a90565b61232a848484840360006125ee565b50505050565b6001600160a01b03831661235a57604051634b637e8f60e11b815260006004820152602401610a90565b6001600160a01b0382166123845760405163ec442f0560e01b815260006004820152602401610a90565b610de98383836126c3565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03831661240c57806002600082825461240191906136aa565b9091555061247e9050565b6001600160a01b0383166000908152602081905260409020548181101561245f5760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610a90565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821661249a576002805482900390556124b9565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516124fe91815260200190565b60405180910390a3505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610de9908490612e62565b6001600160a01b038216600081815260366020908152604091829020805460ff19168515159081179091558251938452908301527f6b4f1be9103e6cbcd38ca4a922334f2c3109b260130a6676a987f94088fd6746910160405180910390a15050565b6001600160a01b0382166000908152603760205260409020805460ff1916821515179055611f2c828261255d565b6001600160a01b0384166126185760405163e602df0560e01b815260006004820152602401610a90565b6001600160a01b03831661264257604051634a1406b160e11b815260006004820152602401610a90565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561232a57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516126b591815260200190565b60405180910390a350505050565b600081116127135760405162461bcd60e51b815260206004820152601d60248201527f616d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610a90565b602e54610100900460ff166127ab576001600160a01b03831660009081526035602052604090205460ff168061276157506001600160a01b03821660009081526035602052604090205460ff165b6127a65760405162461bcd60e51b81526020600482015260166024820152752a3930b234b7339034b9903737ba1030b1ba34bb329760511b6044820152606401610a90565b612814565b6001600160a01b0383166000908152602d602052604090205460ff16156128145760405162461bcd60e51b815260206004820152601e60248201527f536e69706572732063616e6e6f74207472616e7366657220746f6b656e7300006044820152606401610a90565b602854600160a01b900460ff1615612904576001600160a01b03831660009081526035602052604090205460ff1615801561286857506001600160a01b03821660009081526035602052604090205460ff16155b15612904576028546001600160a01b0384811691161480159061289957506028546001600160a01b03838116911614155b6129045760405162461bcd60e51b815260206004820152603660248201527f563320506f6f6c2069732063757272656e746c792070726f7465637465642c206044820152751d1c985b9cd9995c9cc8185c9948191a5cd8589b195960521b6064820152608401610a90565b602e5460ff1615612b9a576001600160a01b03821661dead1480159061294357506001600160a01b03831660009081526035602052604090205460ff16155b801561296857506001600160a01b03821660009081526035602052604090205460ff16155b15612b9a576001600160a01b03831660009081526037602052604090205460ff1680156129ae57506001600160a01b03821660009081526036602052604090205460ff16155b15612a7557602454811115612a165760405162461bcd60e51b815260206004820152602860248201527f427579207472616e7366657220616d6f756e742065786365656473207468652060448201526736b0bc10313abc9760c11b6064820152608401610a90565b602654612a2283610f75565b612a2c90836136aa565b1115612a705760405162461bcd60e51b815260206004820152601360248201527213585e0815d85b1b195d08115e18d959591959606a1b6044820152606401610a90565b612b9a565b6001600160a01b03821660009081526037602052604090205460ff168015612ab657506001600160a01b03831660009081526036602052604090205460ff16155b15612b2057602554811115612a705760405162461bcd60e51b815260206004820152602a60248201527f53656c6c207472616e7366657220616d6f756e742065786365656473207468656044820152691036b0bc1039b2b6361760b11b6064820152608401610a90565b6001600160a01b03821660009081526036602052604090205460ff16612b9a57602654612b4c83610f75565b612b5690836136aa565b1115612b9a5760405162461bcd60e51b815260206004820152601360248201527213585e0815d85b1b195d08115e18d959591959606a1b6044820152606401610a90565b6000612ba530610f75565b60295490915081108015908190612bc45750602e5462010000900460ff165b8015612bda5750602854600160a81b900460ff16155b8015612bfe57506001600160a01b03841660009081526037602052604090205460ff165b15612c2c576028805460ff60a81b1916600160a81b179055612c1e612ed3565b6028805460ff60a81b191690555b6001600160a01b03851660009081526035602052604090205460019060ff1680612c6e57506001600160a01b03851660009081526035602052604090205460ff165b15612c77575060005b60008115612e4e576040805160c081018252601e548152601f546020808301919091528054828401526021546060830152602254608083015260235460a08301526001600160a01b03891660009081526037909152919091205460ff168015612ce4575060008160a00151115b15612d77576103e88160a0015187612cfc91906136bd565b612d0691906136d4565b91508060a00151816020015183612d1d91906136bd565b612d2791906136d4565b602f6000828254612d3891906136aa565b909155505060a08101516060820151612d5190846136bd565b612d5b91906136d4565b60306000828254612d6c91906136aa565b90915550612e2f9050565b6001600160a01b03881660009081526037602052604090205460ff168015612da3575060008160800151115b15612e2f576103e8816080015187612dbb91906136bd565b612dc591906136d4565b6080820151825191935090612dda90846136bd565b612de491906136d4565b602f6000828254612df591906136aa565b909155505060808101516040820151612e0e90846136bd565b612e1891906136d4565b60306000828254612e2991906136aa565b90915550505b8115612e4057612e408830846123e1565b612e4a82876136f6565b9550505b612e598787876123e1565b50505050505050565b600080602060008451602086016000885af180612e85576040513d6000823e3d81fd5b50506000513d91508115612e9d578060011415612eaa565b6001600160a01b0384163b155b1561232a57604051635274afe760e01b81526001600160a01b0385166004820152602401610a90565b6032544314612ee6574360325560006034555b60315460ff168015612efc575060335460345410155b15612f0357565b6000612f0e30610f75565b90506000603054602f54612f2291906136aa565b9050811580612f2f575080155b15612f38575050565b602954612f4690600f6136bd565b821115612f5e57602954612f5b90600f6136bd565b91505b6000612f6983611f8d565b905060006064612f7a83605f6136bd565b612f8491906136d4565b9050612f90848261300c565b602f5447906000908590612fa490846136bd565b612fae91906136d4565b90506000602f819055506000603081905550600160346000828254612fd391906136aa565b9091555050602a54612fee906001600160a01b0316826131c3565b602b54613004906001600160a01b0316476131c3565b505050505050565b6040805160028082526060820183526000926020830190803683370190505090503081600081518110613041576130416134e0565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e3919061350f565b816001815181106130f6576130f66134e0565b60200260200101906001600160a01b031690816001600160a01b031681525050613141307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d856122a5565b60405163791ac94760e01b81526001600160a01b037f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d169063791ac947906131959086908690869030904290600401613709565b600060405180830381600087803b1580156131af57600080fd5b505af1158015612e59573d6000803e3d6000fd5b804710156131ed5760405163cf47918160e01b815247600482015260248101829052604401610a90565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461323a576040519150601f19603f3d011682016040523d82523d6000602084013e61323f565b606091505b5050905080610de95760405163d6bda27560e01b815260040160405180910390fd5b60006020808352835180602085015260005b8181101561328f57858101830151858201604001528201613273565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b0381168114610a9957600080fd5b600080604083850312156132d857600080fd5b82356132e3816132b0565b946020939093013593505050565b60006020828403121561330357600080fd5b813561330e816132b0565b9392505050565b60006020828403121561332757600080fd5b813560ff8116811461330e57600080fd5b60008060006060848603121561334d57600080fd5b8335613358816132b0565b92506020840135613368816132b0565b929592945050506040919091013590565b6000806020838503121561338c57600080fd5b823567ffffffffffffffff808211156133a457600080fd5b818501915085601f8301126133b857600080fd5b8135818111156133c757600080fd5b8660208260051b85010111156133dc57600080fd5b60209290920196919550909350505050565b803580151581146133fe57600080fd5b919050565b6000806040838503121561341657600080fd5b6132e3836133ee565b6000806040838503121561343257600080fd5b823561343d816132b0565b915061344b602084016133ee565b90509250929050565b6000806040838503121561346757600080fd5b8235613472816132b0565b91506020830135613482816132b0565b809150509250929050565b60006020828403121561349f57600080fd5b5035919050565b600181811c908216806134ba57607f821691505b6020821081036134da57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561350857600080fd5b5051919050565b60006020828403121561352157600080fd5b815161330e816132b0565b60008060006060848603121561354157600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052604160045260246000fd5b60008151808452602080850194506020840160005b838110156135aa5781516001600160a01b031687529582019590820190600101613585565b509495945050505050565b8281526040602082015260006135ce6040830184613570565b949350505050565b600060208083850312156135e957600080fd5b825167ffffffffffffffff8082111561360157600080fd5b818501915085601f83011261361557600080fd5b8151818111156136275761362761355a565b8060051b604051601f19603f8301168101818110858211171561364c5761364c61355a565b60405291825284820192508381018501918883111561366a57600080fd5b938501935b828510156136885784518452938501939285019261366f565b98975050505050505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610b4257610b42613694565b8082028115828204841417610b4257610b42613694565b6000826136f157634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610b4257610b42613694565b85815284602082015260a06040820152600061372860a0830186613570565b6001600160a01b039490941660608301525060800152939250505056fea2646970667358221220563d9bb65f5afc119dd277abe25694c6874f669e2f8cc2c1200e920a3c7e5a7364736f6c63430008170033

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

000000000000000000000000ca91a5cb5edba36cd4cee8872035233516c6b1d7000000000000000000000000ef78e11c9a31154753297ee4a196dfce071f16bd

-----Decoded View---------------
Arg [0] : _revShareWallet (address): 0xca91A5cB5EDbA36CD4Cee8872035233516C6B1d7
Arg [1] : _marketingWallet (address): 0xEF78E11C9a31154753297eE4A196dFCE071F16bd

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000ca91a5cb5edba36cd4cee8872035233516c6b1d7
Arg [1] : 000000000000000000000000ef78e11c9a31154753297ee4a196dfce071f16bd


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.