ETH Price: $2,457.10 (-8.34%)

Token

Ruffle Inu (RUFFLE)
 

Overview

Max Total Supply

1,000,000,000 RUFFLE

Holders

297

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
0.000000000000000001 RUFFLE

Value
$0.00
0x9EBC61A3dD7Cd13ce330bc02429c6e86c0661b4c
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
RUFFLE

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 27 : LotteryFinalVersion.sol
//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "hardhat/console.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "./ILottery.sol";
import "./SortitionSumTreeFactory.sol";
import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "./AdvancedTaxFinal.sol";
import "./Multisig.sol";

import "./IPermissions.sol";

contract RUFFLE is ERC20, AdvancedTax {
    using SafeMath for uint256;

    modifier lockSwap() {
        _inSwap = true;
        _;
        _inSwap = false;
    }

    modifier liquidityAdd() {
        _inLiquidityAdd = true;
        _;
        _inLiquidityAdd = false;
    }

    //Token
    uint256 public constant MAX_SUPPLY = 1_000_000_000 ether;
    uint256 public constant maxWallet = 10_000_000 ether; //1%

    mapping(address => uint256) private _balances;
    mapping(address => uint256) private lastBuy;

    /// @notice Contract RUFFLE balance threshold before `_swap` is invoked
    uint256 public minTokenBalance = 9_490_000 ether; //This is the max amount you can win with a 500k buy to not go over max wallet
    bool public swapFees = true;

    //Uniswap
    IUniswapV2Router02 internal _router = IUniswapV2Router02(address(0));
    address internal _pair;
    bool internal _inSwap = false;
    bool internal _inLiquidityAdd = false;
    bool public tradingActive = false;
    uint256 public tradingActiveBlock;
    uint256 public deadBlocks = 2;
    uint256 public cooldown = 45;

    IPermissions public permission;

    event EnableTrading(bool tradingEnabled);
    event RescueLottery(address to, uint256 amount);
    event RescueMarketing(address to, uint256 amount);
    event SetCooldown(uint256 oldCooldown, uint256 newCooldown);
    event SetMinTokenBalance(
        uint256 oldMinTokenBalance,
        uint256 newMinTokenBalance
    );
    event SetSwapFees(bool newValue);
    event Win0SellTax(address indexed winner, bool won);

    event PermissionChanged(address previousPermission, address nextPermission);

    constructor(
        address _uniswapFactory,
        address _uniswapRouter,
        address payable _lotteryWallet,
        address payable _marketingWallet,
        address payable _apadWallet,
        address payable _acapWallet
    ) ERC20("Ruffle Inu", "RUFFLE") Ownable() {
        addTaxExcluded(owner());
        addTaxExcluded(address(0));
        addTaxExcluded(_lotteryWallet);
        addTaxExcluded(_apadWallet);
        addTaxExcluded(_acapWallet);
        addTaxExcluded(address(this));
        addTaxExcluded(_marketingWallet);
        setChanceToWinSellTax(100);
        setChanceToWinLastBuy(200);
        setChanceToWin0SellTax(50);
        _mint(address(this), MAX_SUPPLY);
        lotteryWallet = _lotteryWallet;
        marketingWallet = _marketingWallet;
        acapWallet = _acapWallet;
        apadWallet = _apadWallet;
        _router = IUniswapV2Router02(_uniswapRouter);
        IUniswapV2Factory uniswapContract = IUniswapV2Factory(_uniswapFactory);
        _pair = uniswapContract.createPair(address(this), _router.WETH());
        _secretNumber = uint256(
            keccak256(
                abi.encodePacked(block.timestamp, block.difficulty, msg.sender)
            )
        );
    }

    //receive function
    receive() external payable {}

    /// @notice Add liquidity to uniswap
    /// @param tokens The number of tokens to add liquidity is added
    function addLiquidity(uint256 tokens)
        external
        payable
        onlyOwner
        liquidityAdd
    {
        _approve(address(this), address(_router), tokens);
        _router.addLiquidityETH{value: msg.value}(
            address(this),
            tokens,
            0,
            0,
            owner(),
            // solhint-disable-next-line not-rely-on-time
            block.timestamp
        );
    }

    /// @notice a function to mint and airdrop tokens to an array of accounts
    /// @dev Only use this before adding liquidity and enable trade. Protected by multisig
    function airdrop(address[] memory accounts, uint256[] memory amounts)
        external
        onlyOwner
    {
        require(accounts.length == amounts.length, "array lengths must match");
        for (uint256 i = 0; i < accounts.length; i++) {
            _rawTransfer(address(this), accounts[i], amounts[i]);
        }
    }

    /// @notice Disables trading on Uniswap
    function disableTrading() external onlyOwner {
        require(tradingActive);
        tradingActive = false;
        emit EnableTrading(false);
    }

    /// @notice Enables trading on Uniswap
    /// @param _deadBlocks the number of deadBlocks before trading is open
    function enableTrading(uint256 _deadBlocks) external onlyOwner {
        require(!tradingActive);
        tradingActive = true;
        tradingActiveBlock = block.number;
        deadBlocks = _deadBlocks;
        emit EnableTrading(true);
    }

    /// @notice Rescue ruffle from the lottery
    /// @dev Should only be used in an emergency. Protected by multisig apad
    /// @param amount The amount of ruffle to rescue
    /// @param recipient The recipient of the rescued ruffle
    function rescueLotteryTokens(uint256 amount, address recipient)
        external
        onlyMultisig
    {
        require(
            amount <= totalLottery,
            "Amount cannot be greater than totalLottery"
        );
        _rawTransfer(address(this), recipient, amount);
        totalLottery = totalLottery.sub(amount);
        emit RescueLottery(recipient, amount);
    }

    /// @notice Rescue ruffle from marketing
    /// @dev Should only be used in an emergency. Protected by multisig APAD
    /// @param amount The amount of ruffle to rescue
    /// @param recipient The recipient of the rescued ruffle
    function rescueMarketingTokens(uint256 amount, address recipient)
        external
        onlyMultisig
    {
        require(
            amount <= totalMarketing,
            "Amount cannot be greater than totalMarketing"
        );
        _rawTransfer(address(this), recipient, amount);
        totalMarketing = totalMarketing.sub(amount);
        emit RescueMarketing(recipient, amount);
    }

    /// @notice Change the cooldown for buys
    /// @param _cooldown The new cooldown in seconds
    function setCooldown(uint256 _cooldown) external onlyOwner {
        uint256 _oldValue = cooldown;
        cooldown = _cooldown;
        emit SetCooldown(_oldValue, _cooldown);
    }

    /// @notice Change the minimum contract ruffle balance before `_swap` gets invoked
    /// @param _minTokenBalance The new minimum balance
    function setMinimumTokenBalance(uint256 _minTokenBalance)
        external
        onlyOwner
    {
        require(
            _minTokenBalance < maxWallet,
            "the minimum token balance cannot exceed the maximum wallet"
        );
        uint256 _oldValue = minTokenBalance;
        minTokenBalance = _minTokenBalance;
        emit SetMinTokenBalance(_oldValue, _minTokenBalance);
    }

    /// @notice Enable or disable whether swap occurs during `_transfer`
    /// @param _swapFees If true, enables swap during `_transfer`
    function setSwapFees(bool _swapFees) external onlyOwner {
        swapFees = _swapFees;
        emit SetSwapFees(_swapFees);
    }

    /// @notice Change the whitelist
    /// @param _permission The new whitelist contract
    function setPermissions(IPermissions _permission) external onlyOwner {
        emit PermissionChanged(address(permission), address(_permission));
        permission = _permission;
    }

    /// @notice A function to swap the tokens to eth and send them to marketing,lottery,acap and apad
    /// @notice keeps a minimum balance of tokens in the contract to pay out winners
    function swapAll() external onlyOwner {
        uint256 contractTokenBalance = balanceOf(address(this));

        if (!_inSwap) {
            uint256 _amountAboveMinimumBalance = contractTokenBalance.sub(
                minTokenBalance
            );
            _swap(_amountAboveMinimumBalance);
        }
    }

    /// @notice Function to withdraw all ETH funds from the contract balance
    /// @dev Only in emergency. Protected by multisig APAD
    function withdrawEth() external onlyMultisig {
        payable(owner()).transfer(address(this).balance);
    }

    /// @notice Function to withdraw the ERC20 from the contract balance
    /// @dev Only in emergency. Protected by multisig APAD
    function withdrawTokens() external onlyMultisig {
        _rawTransfer(address(this), msg.sender, balanceOf(address(this)));
    }

    /// @notice Gets the token balance of an address
    /// @param account The address that we want to get the token balance for
    function balanceOf(address account)
        public
        view
        virtual
        override
        returns (uint256)
    {
        return _balances[account];
    }

    function _addBalance(address account, uint256 amount) internal {
        _balances[account] = _balances[account].add(amount);
    }

    function _subtractBalance(address account, uint256 amount) internal {
        _balances[account] = _balances[account].sub(amount);
    }

    /// @notice A function that overrides the standard transfer function and takes into account the taxes
    /// @param sender The sender of the tokens
    /// @param recipient The receiver of the tokens
    /// @param amount The number of tokens that is being sent
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal override {
        if (isTaxExcluded(sender) || isTaxExcluded(recipient)) {
            _rawTransfer(sender, recipient, amount);
            return;
        }

        uint256 contractTokenBalance = balanceOf(address(this));
        bool overMinTokenBalance = contractTokenBalance >= minTokenBalance;

        if (sender != _pair && recipient != _pair) {
            uint256 _lotteryUserBalance = ILottery(lotteryWallet).getBalance(
                recipient
            );
            require(
                amount.add(balanceOf(recipient)).add(_lotteryUserBalance) <
                    maxWallet,
                "the recipient cannot own more than 1 percent of all tokens"
            );
            _rawTransfer(sender, recipient, amount);
        }
        if (overMinTokenBalance && !_inSwap && sender != _pair && swapFees) {
            uint256 _amountAboveMinimumBalance = contractTokenBalance -
                minTokenBalance;
            _swap(_amountAboveMinimumBalance);
        }
        if (address(permission) != address(0)) {
            require(
                permission.isWhitelisted(recipient),
                "User is not whitelisted to buy"
            );
            require(
                amount <= permission.buyLimit(recipient),
                "Buy limit exceeded"
            );
        }
        require(tradingActive, "Trading is not yet active");
        if (sender == _pair) {
            if (cooldown > 0) {
                require(
                    lastBuy[recipient] + cooldown <= block.timestamp,
                    "Cooldown is still active"
                );
            }
            _buyOrder(sender, recipient, amount);
        } else if (recipient == _pair) {
            _sellOrder(sender, recipient, amount);
        }
    }

    /// @notice A function that is being run when someone buys the token
    /// @param sender The pair
    /// @param recipient The receiver of the tokens
    /// @param amount The number of tokens that is being sent
    function _buyOrder(
        address sender,
        address recipient,
        uint256 amount
    ) internal {
        uint256 send = amount;
        uint256 marketing;
        uint256 lottery;
        uint256 acap;
        uint256 apad;
        uint256 buyTax;

        (send, buyTax, marketing, lottery, acap, apad) = _getBuyTaxInfo(
            amount,
            recipient
        );
        taxPercentagePaidByUser[recipient] = buyTax;
        if (buyWinnersActive && amount >= minimumBuyToWin) {
            uint256 amountWon = _getAmountWonOnBuy(recipient, amount, send);
            uint256 amountToTransfer;
            if (amountWon <= totalLottery) {
                amountToTransfer = amountWon;
            } else {
                amountToTransfer = totalLottery;
            }
            _rawTransfer(address(this), recipient, amountToTransfer);
            totalLottery = totalLottery.sub(amountToTransfer);
            amountWonOnBuy[recipient] += amountToTransfer;
            if (amountToTransfer != 0) {
                totalWinners += 1;
                lastAmountWon = amountToTransfer;
                totalTokensWon = totalTokensWon.add(amountToTransfer);
                lastBuyWinner = recipient;
                //               emit BuyWinner(recipient, amountToTransfer);
            }
        }
        require(
            send.add(balanceOf(recipient)).add(
                ILottery(lotteryWallet).getBalance(recipient)
            ) <= maxWallet,
            "you cannot own more than 1 percent of the tokens per wallet"
        );
        _rawTransfer(sender, recipient, send);
        _takeTaxes(sender, marketing, lottery, acap, apad);
        lastBuyAmount = amount;
        lastBuy[recipient] = block.timestamp;
    }

    function _getAmountToMaxWallet(address recipient, uint256 send)
        internal
        returns (uint256)
    {
        uint256 _amountToMaxWallet = maxWallet
            .sub(send)
            .sub(balanceOf(recipient))
            .sub(ILottery(lotteryWallet).getBalance(recipient));
        return _amountToMaxWallet;
    }

    function _getAmountWonOnBuy(
        address recipient,
        uint256 amount,
        uint256 send
    ) internal returns (uint256) {
        uint256 _randomNumberBuyAmount = _getPseudoRandomNumber(
            chanceToWinLastBuy,
            send,
            recipient
        );
        uint256 _randomNumberLastSellTax = _getPseudoRandomNumber(
            chanceToWinSellTax,
            send,
            recipient
        );
        uint256 _winningNumberBuy = _secretNumber.mod(chanceToWinLastBuy);
        uint256 _winningNumberSellTax = _secretNumber.mod(chanceToWinSellTax);
        uint256 amountToMaxWallet = _getAmountToMaxWallet(recipient, send);
        uint256 amountWonToTransfer;
        if (
            _randomNumberBuyAmount == _winningNumberBuy &&
            wonLastBuy[recipient] == false
        ) {
            if (lastBuyAmount <= amountToMaxWallet) {
                amountWonToTransfer = lastBuyAmount;
            } else {
                amountWonToTransfer = amountToMaxWallet;
            }
            wonLastBuy[recipient] = true;
        } else if (_randomNumberLastSellTax == _winningNumberSellTax) {
            if (lastSellTax <= amountToMaxWallet) {
                amountWonToTransfer = lastSellTax;
            } else {
                amountWonToTransfer = amountToMaxWallet;
            }
        }
        return amountWonToTransfer;
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    function _mint(address account, uint256 amount) internal override {
        require(_totalSupply.add(amount) <= MAX_SUPPLY, "Max supply exceeded");
        _totalSupply = _totalSupply.add(amount);
        _addBalance(account, amount);
        emit Transfer(address(0), account, amount);
    }

    function _rawTransfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal {
        require(sender != address(0), "transfer from the zero address");
        require(recipient != address(0), "transfer to the zero address");

        uint256 senderBalance = balanceOf(sender);
        require(senderBalance >= amount, "transfer amount exceeds balance");
        unchecked {
            _subtractBalance(sender, amount);
        }
        _addBalance(recipient, amount);

        emit Transfer(sender, recipient, amount);
    }

    /// @notice A function that is being run when someone sells a token
    /// @param sender The sender of the tokens
    /// @param recipient the uniswap pair
    /// @param amount The number of tokens that is being sent
    function _sellOrder(
        address sender,
        address recipient,
        uint256 amount
    ) internal {
        uint256 send = amount;
        uint256 marketing;
        uint256 lottery;
        uint256 totalTax;
        uint256 acap;
        uint256 apad;
        (send, totalTax, marketing, lottery, acap, apad) = _getSellTaxInfo(
            amount,
            recipient
        );
        if (totalTax == 0) {
            won0SellTax[sender] = true;
            _rawTransfer(sender, recipient, send);
            totalWinners += 1;
            emit Win0SellTax(sender, true);
        } else {
            _rawTransfer(sender, recipient, send);
            _takeTaxes(sender, marketing, lottery, acap, apad);
            uint256 _sellTaxRefundPercentage = _getSellTaxPercentage(
                amount,
                recipient
            );
            uint256 refund;
            refund = _sellTaxRefundPercentage.mul(amount).div(100);
            if (refund <= totalLottery) {
                lastSellTax = totalTax.sub(refund);
                totalLottery = totalLottery.sub(refund);
                if (refund != 0) {
                    _rawTransfer(address(this), recipient, refund);
                }
            }
        }
    }

    /// @notice Perform a Uniswap v2 swap from ruffle to ETH and handle tax distribution
    /// @param amount The amount of ruffle to swap in wei
    /// @dev `amount` is always <= this contract's ETH balance. Calculate and distribute marketing taxes
    function _swap(uint256 amount) internal lockSwap {
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = _router.WETH();

        _approve(address(this), address(_router), amount);

        uint256 contractEthBalance = address(this).balance;

        _router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            amount,
            0,
            path,
            address(this),
            block.timestamp
        );

        uint256 tradeValue = address(this).balance.sub(contractEthBalance);

        uint256 totalTaxes = totalMarketing
            .add(totalLottery)
            .add(totalAcap)
            .add(totalApad);
        uint256 marketingAmount = amount.mul(totalMarketing).div(totalTaxes);
        uint256 lotteryAmount = amount.mul(totalLottery).div(totalTaxes);
        uint256 acapAmount = amount.mul(totalAcap).div(totalTaxes);
        uint256 apadAmount = amount.mul(totalApad).div(totalTaxes);

        uint256 marketingEth = tradeValue.mul(totalMarketing).div(totalTaxes);
        uint256 lotteryEth = tradeValue.mul(totalLottery).div(totalTaxes);
        uint256 acapEth = tradeValue.mul(totalAcap).div(totalTaxes);
        uint256 apadEth = tradeValue.mul(totalApad).div(totalTaxes);

        if (marketingEth > 0) {
            marketingWallet.transfer(marketingEth);
        }
        if (lotteryEth > 0) {
            lotteryWallet.transfer(lotteryEth);
        }
        if (acapEth > 0) {
            acapWallet.transfer(acapEth);
        }
        if (apadEth > 0) {
            apadWallet.transfer(apadEth);
        }
        totalMarketing = totalMarketing.sub(marketingAmount);
        totalLottery = totalLottery.sub(lotteryAmount);
        totalAcap = totalAcap.sub(acapAmount);
        totalApad = totalApad.sub(apadAmount);
    }

    /// @notice Transfers ruffle from an account to this contract for taxes
    /// @param _account The account to transfer ruffle from
    /// @param _marketingAmount The amount of marketing tax to transfer
    /// @param _lotteryAmount The amount of treasury tax to transfer
    function _takeTaxes(
        address _account,
        uint256 _marketingAmount,
        uint256 _lotteryAmount,
        uint256 _acapAmount,
        uint256 _apadAmount
    ) internal {
        require(_account != address(0), "taxation from the zero address");

        uint256 totalAmount = _marketingAmount
            .add(_lotteryAmount)
            .add(_acapAmount)
            .add(_apadAmount);
        _rawTransfer(_account, address(this), totalAmount);
        totalMarketing = totalMarketing.add(_marketingAmount);
        totalLottery = totalLottery.add(_lotteryAmount);
        totalAcap = totalAcap.add(_acapAmount);
        totalApad = totalApad.add(_apadAmount);
    }

    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }
}

import "./SortitionSumTreeFactory.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

contract Lottery is Ownable, VRFConsumerBaseV2, IERC721Receiver, Multisig {
    using SortitionSumTreeFactory for SortitionSumTreeFactory.SortitionSumTrees;
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    using EnumerableSet for EnumerableSet.AddressSet;
    mapping(address => bool) internal _whitelistedServices;

    IERC721 public nft721;
    uint256 public nftId;
    IERC20 public customToken;
    IERC20 public ruffle;

    address payable[] public selectedWinners;
    address[] public lastWinners;
    uint256[] public winningNumbers;
    uint256 public jackpot;
    uint256 public lastJackpot;
    uint256 public totalEthPaid;
    uint256 public totalWinnersPaid;
    uint256[] public percentageOfJackpot = [75, 18, 7];
    mapping(address => uint256) public amountWonByUser;

    enum Status {
        NotStarted,
        Started,
        WinnersSelected,
        WinnerPaid
    }
    Status public status;

    enum LotteryType {
        NotStarted,
        Ethereum,
        Token,
        NFT721
    }
    LotteryType public lotteryType;

    //Staking
    uint256 public totalStaked;
    mapping(address => uint256) public balanceOf;
    bool public stakingEnabled;

    //Variables used for the sortitionsumtrees
    bytes32 private constant TREE_KEY = keccak256("Lotto");
    uint256 private constant MAX_TREE_LEAVES = 5;

    // Ticket-weighted odds
    SortitionSumTreeFactory.SortitionSumTrees internal sortitionSumTrees;

    // Chainlink
    VRFCoordinatorV2Interface COORDINATOR;
    LinkTokenInterface LINKTOKEN;
    uint64 s_subscriptionId;

    // Mainnet coordinator. 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    address constant vrfCoordinator =
        0x271682DEB8C4E0901D1a1550aD2e64D568E69909;

    // Mainnet LINK token contract. 0x514910771af9ca656af840dff83e8264ecf986ca
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    address constant link = 0x514910771AF9Ca656af840dff83E8264EcF986CA;

    // 200 gwei Key Hash lane for chainlink mainnet
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    bytes32 constant keyHash =
        0x8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef;

    uint32 constant callbackGasLimit = 500000;
    uint16 constant requestConfirmations = 3;

    // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS.
    uint32 numWords = 3;

    uint256[] public s_randomWords;
    uint256 public s_requestId;
    address s_owner;

    event AddWhitelistedService(address newWhitelistedAddress);
    event RemoveWhitelistedService(address removedWhitelistedAddress);
    event SetCustomToken(IERC20 tokenAddress);
    event SetRuffleInuToken(IERC20 ruffleInuTokenAddress);
    event Staked(address indexed account, uint256 amount);
    event Unstaked(address indexed account, uint256 amount);
    event SetERC721(IERC721 nft);
    event SetPercentageOfJackpot(
        uint256[] newJackpotPercentages,
        uint256 newNumWords
    );
    event UpdateSubscription(
        uint256 oldSubscriptionId,
        uint256 newSubscriptionId
    );
    event EthLotteryStarted(uint256 jackpot, uint256 numberOfWinners);
    event TokenLotteryStarted(uint256 jackpot, uint256 numberOfWinners);
    event NFTLotteryStarted(uint256 nftId);
    event PayWinnersEth(address[] winners);
    event PayWinnersTokens(address[] winners);
    event PayWinnerNFT(address[] winners);
    event SetStakingEnabled(bool stakingEnabled);

    constructor(uint64 subscriptionId, address payable _gelatoOp)
        VRFConsumerBaseV2(vrfCoordinator)
    {
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        LINKTOKEN = LinkTokenInterface(link);
        sortitionSumTrees.createTree(TREE_KEY, MAX_TREE_LEAVES);
        s_owner = msg.sender;
        s_subscriptionId = subscriptionId;
        addWhitelistedService(_gelatoOp);
        addWhitelistedService(msg.sender);
    }

    modifier onlyWhitelistedServices() {
        require(
            _whitelistedServices[msg.sender] == true,
            "onlyWhitelistedServices can perform this action"
        );
        _;
    }

    modifier lotteryNotStarted() {
        require(
            status == Status.NotStarted || status == Status.WinnerPaid,
            "lottery has already started"
        );
        require(
            lotteryType == LotteryType.NotStarted,
            "the previous winner has to be paid before starting a new lottery"
        );
        _;
    }

    modifier winnerPayable() {
        require(
            status == Status.WinnersSelected,
            "the winner is not yet selected"
        );
        _;
    }

    //Receive function
    receive() external payable {}

    /// @notice Add new service that can call payWinnersEth and startEthLottery.
    /// @param _service New service to add
    function addWhitelistedService(address _service) public onlyOwner {
        require(
            _whitelistedServices[_service] != true,
            "TaskTreasury: addWhitelistedService: whitelisted"
        );
        _whitelistedServices[_service] = true;
        emit AddWhitelistedService(_service);
    }

    /// @notice Remove old service that can call startEthLottery and payWinnersEth
    /// @param _service Old service to remove
    function removeWhitelistedService(address _service) external onlyOwner {
        require(
            _whitelistedServices[_service] == true,
            "addWhitelistedService: !whitelisted"
        );
        _whitelistedServices[_service] = false;
        emit RemoveWhitelistedService(_service);
    }

    /// @notice a function to cancel the current lottery in case the chainlink vrf fails
    /// @dev only call this when the chainlink vrf fails

    function cancelLottery() external onlyOwner {
        require(
            status == Status.Started || status == Status.WinnersSelected,
            "you can only cancel a lottery if one has been started or if something goes wrong after selection"
        );
        jackpot = 0;
        setStakingEnabled(true);
        status = Status.WinnerPaid;
        lotteryType = LotteryType.NotStarted;
        delete selectedWinners;
    }

    /// @notice draw the winning addresses from the Sum Tree
    function draw() external onlyOwner {
        require(status == Status.Started, "lottery has not yen been started");
        for (uint256 i = 0; i < s_randomWords.length; i++) {
            uint256 winningNumber = s_randomWords[i] % totalStaked;
            selectedWinners.push(
                payable(
                    address(
                        uint160(
                            uint256(
                                sortitionSumTrees.draw(TREE_KEY, winningNumber)
                            )
                        )
                    )
                )
            );
            winningNumbers.push(winningNumber);
        }
        status = Status.WinnersSelected;
    }

    /// @notice function needed to receive erc721 tokens in the contract
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external pure override returns (bytes4) {
        return
            bytes4(
                keccak256("onERC721Received(address,address,uint256,bytes)")
            );
    }

    /// @notice pay the winners of the lottery
    function payWinnersTokens() external onlyOwner winnerPayable {
        require(
            lotteryType == LotteryType.Token,
            "the lottery that has been drawn is not a custom lottery"
        );

        delete lastWinners;
        for (uint256 i = 0; i < selectedWinners.length; i++) {
            uint256 _amountWon = jackpot.mul(percentageOfJackpot[i]).div(100);
            customToken.safeTransfer(selectedWinners[i], _amountWon);
            lastWinners.push(selectedWinners[i]);
            amountWonByUser[selectedWinners[i]] += _amountWon;
        }
        lastJackpot = jackpot;
        totalWinnersPaid += selectedWinners.length;
        delete selectedWinners;
        jackpot = 0;
        setStakingEnabled(true);
        status = Status.WinnerPaid;
        lotteryType = LotteryType.NotStarted;
        emit PayWinnersTokens(lastWinners);
    }

    /// @notice pay the winners of the lottery
    function payWinnersEth() external onlyWhitelistedServices winnerPayable {
        require(
            lotteryType == LotteryType.Ethereum,
            "the lottery that has been drawn is not an eth lottery"
        );

        delete lastWinners;
        for (uint256 i = 0; i < selectedWinners.length; i++) {
            uint256 _amountWon = jackpot.mul(percentageOfJackpot[i]).div(100);
            selectedWinners[i].transfer(_amountWon);
            lastWinners.push(selectedWinners[i]);
            amountWonByUser[selectedWinners[i]] += _amountWon;
        }
        lastJackpot = jackpot;
        totalEthPaid += jackpot;
        totalWinnersPaid += selectedWinners.length;
        delete selectedWinners;
        jackpot = 0;
        setStakingEnabled(true);
        status = Status.WinnerPaid;
        lotteryType = LotteryType.NotStarted;
        emit PayWinnersEth(lastWinners);
    }

    /// @notice pay the winners of the lottery
    function payWinnersERC721() external onlyOwner winnerPayable {
        require(
            lotteryType == LotteryType.NFT721,
            "the lottery that has been drawn is not a ERC721 lottery"
        );

        delete lastWinners;
        nft721.safeTransferFrom(address(this), selectedWinners[0], nftId);
        lastWinners.push(selectedWinners[0]);
        totalWinnersPaid += 1;
        delete selectedWinners;
        setStakingEnabled(true);
        status = Status.WinnerPaid;
        lotteryType = LotteryType.NotStarted;
        emit PayWinnerNFT(lastWinners);
    }

    /// @notice a function to add a custom token for a custom token lottery
    /// @param customTokenAddress the address of the custom token that we want to add to the contract
    function setCustomToken(IERC20 customTokenAddress) external onlyOwner {
        customToken = IERC20(customTokenAddress);

        emit SetCustomToken(customTokenAddress);
    }

    /// @notice a function to set the address of the ruffle token
    /// @param ruffleAddress is the address of the ruffle token
    function setRuffleInuToken(IERC20 ruffleAddress) external onlyOwner {
        ruffle = IERC20(ruffleAddress);
        emit SetRuffleInuToken(ruffleAddress);
    }

    /// @notice add erc721 token to the contract for the next lottery
    function setERC721(IERC721 _nft) external onlyOwner {
        nft721 = IERC721(_nft);
        emit SetERC721(_nft);
    }

    /// @notice a function to set the jackpot distribution
    /// @param percentages an array of the percentage distribution
    function setPercentageOfJackpot(uint256[] memory percentages)
        external
        onlyOwner
    {
        require(
            status == Status.NotStarted || status == Status.WinnerPaid,
            "you can only change the jackpot percentages if the lottery is not running"
        );
        delete percentageOfJackpot;
        uint256 _totalSum = 0;
        for (uint256 i; i < percentages.length; i++) {
            percentageOfJackpot.push(percentages[i]);
            _totalSum = _totalSum.add(percentages[i]);
        }
        require(_totalSum == 100, "the sum of the percentages has to be 100");
        numWords = uint32(percentages.length);
        emit SetPercentageOfJackpot(percentages, numWords);
    }

    /// @notice Stakes tokens. NOTE: Staking and unstaking not possible during lottery draw
    /// @param amount Amount to stake and lock
    function stake(uint256 amount) external {
        require(stakingEnabled, "staking is not open");
        if (balanceOf[msg.sender] == 0) {
            sortitionSumTrees.set(
                TREE_KEY,
                amount,
                bytes32(uint256(uint160(address(msg.sender))))
            );
        } else {
            uint256 _newValue = balanceOf[msg.sender].add(amount);
            sortitionSumTrees.set(
                TREE_KEY,
                _newValue,
                bytes32(uint256(uint160(address(msg.sender))))
            );
        }
        ruffle.safeTransferFrom(msg.sender, address(this), amount);
        balanceOf[msg.sender] = balanceOf[msg.sender].add(amount);
        totalStaked = totalStaked.add(amount);
        emit Staked(msg.sender, amount);
    }

    /// @notice Start a new lottery
    /// @param _amount in tokens to add to this lottery
    function startTokenLottery(uint256 _amount)
        external
        onlyOwner
        lotteryNotStarted
    {
        require(
            _amount <= customToken.balanceOf(address(this)),
            "The jackpot has to be less than or equal to the tokens in the contract"
        );

        delete winningNumbers;
        delete s_randomWords;
        setStakingEnabled(false);
        requestRandomWords();
        jackpot = _amount;
        status = Status.Started;
        lotteryType = LotteryType.Token;
        emit TokenLotteryStarted(jackpot, numWords);
    }

    /// @notice Start a new lottery
    /// @param _amount The amount in eth to add to this lottery
    function startEthLottery(uint256 _amount)
        external
        onlyWhitelistedServices
        lotteryNotStarted
    {
        require(
            _amount <= address(this).balance,
            "You can maximum add all the eth in the contract balance"
        );
        delete winningNumbers;
        delete s_randomWords;
        setStakingEnabled(false);
        requestRandomWords();
        jackpot = _amount;
        status = Status.Started;
        lotteryType = LotteryType.Ethereum;
        emit EthLotteryStarted(jackpot, numWords);
    }

    /// @notice Start a new nft lottery
    /// @param _tokenId the id of the nft you want to give away in the lottery
    /// @dev set the jackpot to 1 winner [100] before calling this function
    function startERC721Lottery(uint256 _tokenId)
        external
        onlyOwner
        lotteryNotStarted
    {
        require(nft721.ownerOf(_tokenId) == address(this));
        require(
            percentageOfJackpot.length == 1,
            "jackpot has to be set to 1 winner first, percentageOfJackpot = [100]"
        );
        delete winningNumbers;
        delete s_randomWords;
        nftId = _tokenId;
        setStakingEnabled(false);
        requestRandomWords();
        status = Status.Started;
        lotteryType = LotteryType.NFT721;
        emit NFTLotteryStarted(nftId);
    }

    /// @notice Withdraws staked tokens
    /// @param _amount Amount to withdraw
    function unstake(uint256 _amount) external {
        require(stakingEnabled, "staking is not open");
        require(
            _amount <= balanceOf[msg.sender],
            "you cannot unstake more than you have staked"
        );
        uint256 _newStakingBalance = balanceOf[msg.sender].sub(_amount);
        sortitionSumTrees.set(
            TREE_KEY,
            _newStakingBalance,
            bytes32(uint256(uint160(address(msg.sender))))
        );
        balanceOf[msg.sender] = _newStakingBalance;
        totalStaked = totalStaked.sub(_amount);
        ruffle.safeTransfer(msg.sender, _amount);

        emit Unstaked(msg.sender, _amount);
    }

    /// @notice function to update the chainlink subscription
    /// @param subscriptionId Amount to withdraw
    function updateSubscription(uint64 subscriptionId) external {
        uint256 _oldValue = s_subscriptionId;
        s_subscriptionId = subscriptionId;
        emit UpdateSubscription(_oldValue, subscriptionId);
    }

    /// @notice Emergency withdraw only call when problems or after community vote
    /// @dev Only in emergency cases. Protected by multisig APAD
    function withdraw() external onlyMultisig {
        payable(msg.sender).transfer(address(this).balance);
    }

    /// @notice The chance a user has of winning the lottery. Tokens staked by user / total tokens staked
    /// @param account The account that we want to get the chance of winning for
    /// @return chanceOfWinning The chance a user has to win
    function chanceOf(address account)
        external
        view
        returns (uint256 chanceOfWinning)
    {
        return
            sortitionSumTrees.stakeOf(
                TREE_KEY,
                bytes32(uint256(uint160(address(account))))
            );
    }

    /// @notice get the staked ruffle balance of an address
    function getBalance(address staker)
        external
        view
        returns (uint256 balance)
    {
        return balanceOf[staker];
    }

    /// @notice a function to set open/close staking
    function setStakingEnabled(bool _stakingEnabled)
        public
        onlyWhitelistedServices
    {
        stakingEnabled = _stakingEnabled;
        emit SetStakingEnabled(_stakingEnabled);
    }

    /// @notice Request random words from Chainlink VRF V2
    function requestRandomWords() internal {
        // Will revert if subscription is not set and funded.
        s_requestId = COORDINATOR.requestRandomWords(
            keyHash,
            s_subscriptionId,
            requestConfirmations,
            callbackGasLimit,
            numWords
        );
    }

    /// @notice fulfill the randomwords from chainlink
    function fulfillRandomWords(
        uint256, /* requestId */
        uint256[] memory randomWords
    ) internal override {
        s_randomWords = randomWords;
        if (s_randomWords.length <= 5) {
            for (uint256 i = 0; i < s_randomWords.length; i++) {
                uint256 winningNumber = s_randomWords[i] % totalStaked;
                selectedWinners.push(
                    payable(
                        address(
                            uint160(
                                uint256(
                                    sortitionSumTrees.draw(
                                        TREE_KEY,
                                        winningNumber
                                    )
                                )
                            )
                        )
                    )
                );
                winningNumbers.push(winningNumber);
            }
            status = Status.WinnersSelected;
        }
    }
}

File 2 of 27 : VRFConsumerBaseV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/** ****************************************************************************
 * @notice Interface for contracts using VRF randomness
 * *****************************************************************************
 * @dev PURPOSE
 *
 * @dev Reggie the Random Oracle (not his real job) wants to provide randomness
 * @dev to Vera the verifier in such a way that Vera can be sure he's not
 * @dev making his output up to suit himself. Reggie provides Vera a public key
 * @dev to which he knows the secret key. Each time Vera provides a seed to
 * @dev Reggie, he gives back a value which is computed completely
 * @dev deterministically from the seed and the secret key.
 *
 * @dev Reggie provides a proof by which Vera can verify that the output was
 * @dev correctly computed once Reggie tells it to her, but without that proof,
 * @dev the output is indistinguishable to her from a uniform random sample
 * @dev from the output space.
 *
 * @dev The purpose of this contract is to make it easy for unrelated contracts
 * @dev to talk to Vera the verifier about the work Reggie is doing, to provide
 * @dev simple access to a verifiable source of randomness. It ensures 2 things:
 * @dev 1. The fulfillment came from the VRFCoordinator
 * @dev 2. The consumer contract implements fulfillRandomWords.
 * *****************************************************************************
 * @dev USAGE
 *
 * @dev Calling contracts must inherit from VRFConsumerBase, and can
 * @dev initialize VRFConsumerBase's attributes in their constructor as
 * @dev shown:
 *
 * @dev   contract VRFConsumer {
 * @dev     constructor(<other arguments>, address _vrfCoordinator, address _link)
 * @dev       VRFConsumerBase(_vrfCoordinator) public {
 * @dev         <initialization with other arguments goes here>
 * @dev       }
 * @dev   }
 *
 * @dev The oracle will have given you an ID for the VRF keypair they have
 * @dev committed to (let's call it keyHash). Create subscription, fund it
 * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface
 * @dev subscription management functions).
 * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,
 * @dev callbackGasLimit, numWords),
 * @dev see (VRFCoordinatorInterface for a description of the arguments).
 *
 * @dev Once the VRFCoordinator has received and validated the oracle's response
 * @dev to your request, it will call your contract's fulfillRandomWords method.
 *
 * @dev The randomness argument to fulfillRandomWords is a set of random words
 * @dev generated from your requestId and the blockHash of the request.
 *
 * @dev If your contract could have concurrent requests open, you can use the
 * @dev requestId returned from requestRandomWords to track which response is associated
 * @dev with which randomness request.
 * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind,
 * @dev if your contract could have multiple requests in flight simultaneously.
 *
 * @dev Colliding `requestId`s are cryptographically impossible as long as seeds
 * @dev differ.
 *
 * *****************************************************************************
 * @dev SECURITY CONSIDERATIONS
 *
 * @dev A method with the ability to call your fulfillRandomness method directly
 * @dev could spoof a VRF response with any random value, so it's critical that
 * @dev it cannot be directly called by anything other than this base contract
 * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
 *
 * @dev For your users to trust that your contract's random behavior is free
 * @dev from malicious interference, it's best if you can write it so that all
 * @dev behaviors implied by a VRF response are executed *during* your
 * @dev fulfillRandomness method. If your contract must store the response (or
 * @dev anything derived from it) and use it later, you must ensure that any
 * @dev user-significant behavior which depends on that stored value cannot be
 * @dev manipulated by a subsequent VRF request.
 *
 * @dev Similarly, both miners and the VRF oracle itself have some influence
 * @dev over the order in which VRF responses appear on the blockchain, so if
 * @dev your contract could have multiple VRF requests in flight simultaneously,
 * @dev you must ensure that the order in which the VRF responses arrive cannot
 * @dev be used to manipulate your contract's user-significant behavior.
 *
 * @dev Since the block hash of the block which contains the requestRandomness
 * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
 * @dev miner could, in principle, fork the blockchain to evict the block
 * @dev containing the request, forcing the request to be included in a
 * @dev different block with a different hash, and therefore a different input
 * @dev to the VRF. However, such an attack would incur a substantial economic
 * @dev cost. This cost scales with the number of blocks the VRF oracle waits
 * @dev until it calls responds to a request. It is for this reason that
 * @dev that you can signal to an oracle you'd like them to wait longer before
 * @dev responding to the request (however this is not enforced in the contract
 * @dev and so remains effective only in the case of unmodified oracle software).
 */
abstract contract VRFConsumerBaseV2 {
  error OnlyCoordinatorCanFulfill(address have, address want);
  address private immutable vrfCoordinator;

  /**
   * @param _vrfCoordinator address of VRFCoordinator contract
   */
  constructor(address _vrfCoordinator) {
    vrfCoordinator = _vrfCoordinator;
  }

  /**
   * @notice fulfillRandomness handles the VRF response. Your contract must
   * @notice implement it. See "SECURITY CONSIDERATIONS" above for important
   * @notice principles to keep in mind when implementing your fulfillRandomness
   * @notice method.
   *
   * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this
   * @dev signature, and will call it once it has verified the proof
   * @dev associated with the randomness. (It is triggered via a call to
   * @dev rawFulfillRandomness, below.)
   *
   * @param requestId The Id initially returned by requestRandomness
   * @param randomWords the VRF output expanded to the requested number of words
   */
  function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;

  // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
  // proof. rawFulfillRandomness then calls fulfillRandomness, after validating
  // the origin of the call
  function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
    if (msg.sender != vrfCoordinator) {
      revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
    }
    fulfillRandomWords(requestId, randomWords);
  }
}

File 3 of 27 : LinkTokenInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);

  function approve(address spender, uint256 value) external returns (bool success);

  function balanceOf(address owner) external view returns (uint256 balance);

  function decimals() external view returns (uint8 decimalPlaces);

  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);

  function increaseApproval(address spender, uint256 subtractedValue) external;

  function name() external view returns (string memory tokenName);

  function symbol() external view returns (string memory tokenSymbol);

  function totalSupply() external view returns (uint256 totalTokensIssued);

  function transfer(address to, uint256 value) external returns (bool success);

  function transferAndCall(
    address to,
    uint256 value,
    bytes calldata data
  ) external returns (bool success);

  function transferFrom(
    address from,
    address to,
    uint256 value
  ) external returns (bool success);
}

File 4 of 27 : VRFCoordinatorV2Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface VRFCoordinatorV2Interface {
  /**
   * @notice Get configuration relevant for making requests
   * @return minimumRequestConfirmations global min for request confirmations
   * @return maxGasLimit global max for request gas limit
   * @return s_provingKeyHashes list of registered key hashes
   */
  function getRequestConfig()
    external
    view
    returns (
      uint16,
      uint32,
      bytes32[] memory
    );

  /**
   * @notice Request a set of random words.
   * @param keyHash - Corresponds to a particular oracle job which uses
   * that key for generating the VRF proof. Different keyHash's have different gas price
   * ceilings, so you can select a specific one to bound your maximum per request cost.
   * @param subId  - The ID of the VRF subscription. Must be funded
   * with the minimum subscription balance required for the selected keyHash.
   * @param minimumRequestConfirmations - How many blocks you'd like the
   * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS
   * for why you may want to request more. The acceptable range is
   * [minimumRequestBlockConfirmations, 200].
   * @param callbackGasLimit - How much gas you'd like to receive in your
   * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords
   * may be slightly less than this amount because of gas used calling the function
   * (argument decoding etc.), so you may need to request slightly more than you expect
   * to have inside fulfillRandomWords. The acceptable range is
   * [0, maxGasLimit]
   * @param numWords - The number of uint256 random values you'd like to receive
   * in your fulfillRandomWords callback. Note these numbers are expanded in a
   * secure way by the VRFCoordinator from a single random value supplied by the oracle.
   * @return requestId - A unique identifier of the request. Can be used to match
   * a request to a response in fulfillRandomWords.
   */
  function requestRandomWords(
    bytes32 keyHash,
    uint64 subId,
    uint16 minimumRequestConfirmations,
    uint32 callbackGasLimit,
    uint32 numWords
  ) external returns (uint256 requestId);

  /**
   * @notice Create a VRF subscription.
   * @return subId - A unique subscription id.
   * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
   * @dev Note to fund the subscription, use transferAndCall. For example
   * @dev  LINKTOKEN.transferAndCall(
   * @dev    address(COORDINATOR),
   * @dev    amount,
   * @dev    abi.encode(subId));
   */
  function createSubscription() external returns (uint64 subId);

  /**
   * @notice Get a VRF subscription.
   * @param subId - ID of the subscription
   * @return balance - LINK balance of the subscription in juels.
   * @return reqCount - number of requests for this subscription, determines fee tier.
   * @return owner - owner of the subscription.
   * @return consumers - list of consumer address which are able to use this subscription.
   */
  function getSubscription(uint64 subId)
    external
    view
    returns (
      uint96 balance,
      uint64 reqCount,
      address owner,
      address[] memory consumers
    );

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @param newOwner - proposed new owner of the subscription
   */
  function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external;

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @dev will revert if original owner of subId has
   * not requested that msg.sender become the new owner.
   */
  function acceptSubscriptionOwnerTransfer(uint64 subId) external;

  /**
   * @notice Add a consumer to a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - New consumer which can use the subscription
   */
  function addConsumer(uint64 subId, address consumer) external;

  /**
   * @notice Remove a consumer from a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - Consumer to remove from the subscription
   */
  function removeConsumer(uint64 subId, address consumer) external;

  /**
   * @notice Cancel a subscription
   * @param subId - ID of the subscription
   * @param to - Where to send the remaining LINK to
   */
  function cancelSubscription(uint64 subId, address to) external;
}

File 5 of 27 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.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}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * 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 ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * 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 override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override 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 value {ERC20} uses, unless this function is
     * 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 override returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override 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 `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` 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 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * 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 `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * 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.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` 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.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

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

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 8 of 27 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
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 9 of 27 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/Address.sol";

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

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

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

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

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

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

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

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

File 10 of 27 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 11 of 27 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 12 of 27 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

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

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

File 14 of 27 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * 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[EIP 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);
}

File 15 of 27 : SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 16 of 27 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly {
            result := store
        }

        return result;
    }
}

File 17 of 27 : IUniswapV2Factory.sol
pragma solidity >=0.5.0;

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

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

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

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

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

File 18 of 27 : IUniswapV2Pair.sol
pragma solidity >=0.5.0;

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

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

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

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

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

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

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

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

    function initialize(address, address) external;
}

File 19 of 27 : IUniswapV2Router01.sol
pragma solidity >=0.6.2;

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 20 of 27 : IUniswapV2Router02.sol
pragma solidity >=0.6.2;

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 21 of 27 : AdvancedTaxFinal.sol
//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "./WinOnBuy.sol";
import "./Multisig.sol";

contract AdvancedTax is Ownable, WinOnBuy, Multisig {
    using SafeMath for uint256;

    uint256 _totalSupply;
    //Tax distribution between marketing and lottery. Tax percentage is variable on buy and sell
    uint256 public buyMarketingRate = 20;
    uint256 public buyLotteryRate = 60;
    uint256 public buyAcapRate = 8;
    uint256 public buyApadRate = 12;
    uint256 public sellMarketingRate = 30;
    uint256 public sellLotteryRate = 50;
    uint256 public sellAcapRate = 4;
    uint256 public sellApadRate = 16;
    uint256 public minimumBuyTax = 12;
    uint256 public buyTaxRange = 0;
    uint256 public maximumSellTax = 25; //The selltaxrefund will be deducted so that max effective sell tax is never higher than 20 percent
    uint256 public maximumSellTaxRefund = 0; //dynamic
    uint256[] public tieredTaxPercentage = [10, 10, 10];
    uint256[] public taxTiers = [50, 10]; //Highest bracket, middle bracket. multiplied by TotalSupply divided by 10000

    //Tax balances
    uint256 public totalMarketing;
    uint256 public totalLottery;
    uint256 public totalApad;
    uint256 public totalAcap;

    //Tax wallets
    address payable public lotteryWallet;
    address payable public marketingWallet;
    address payable public apadWallet;
    address payable public acapWallet;

    mapping(address => bool) public _taxExcluded;
    mapping(address => uint256) public taxPercentagePaidByUser;

    //event
    event AddTaxExcluded(address wallet);
    event RemoveTaxExcluded(address wallet);
    event SetBuyRate(
        uint256 buyMarketingRate,
        uint256 buyLotteryRate,
        uint256 buyAcapRate,
        uint256 buyApadRate
    );
    event SetBuyTax(uint256 minimumBuyTax, uint256 buyTaxRange);
    event SetLotteryWallet(address oldLotteryWallet, address newLotteryWallet);
    event SetMarketingWallet(
        address oldMarketingWallet,
        address newMarketingWallet
    );
    event SetSellRates(
        uint256 sellMarketingRate,
        uint256 sellLotteryRate,
        uint256 sellAcapRate,
        uint256 sellApadRate
    );
    event SetSellTax(uint256 _maximumSellTax, uint256 _maximumSellTaxRefund);
    event SetTaxTiers(uint256 tier1, uint256 tier2);
    event SetTieredTaxPercentages(uint256 multiplier1, uint256 multiplier2);

    /// @notice Include an address to paying taxes
    /// @param account The address that we want to start paying taxes
    function removeTaxExcluded(address account) public onlyOwner {
        require(isTaxExcluded(account), "Account must not be excluded");
        _taxExcluded[account] = false;
        emit RemoveTaxExcluded(account);
    }

    /// @notice Change distribution of the buy taxes
    /// @param _marketingRate The new marketing tax rate
    /// @param _buyLotteryRate The new lottery tax rate
    /// @param _buyAcapRate The new acap tax rate
    /// @param _buyApadRate The new apad tax rate
    function setBuyRates(
        uint256 _marketingRate,
        uint256 _buyLotteryRate,
        uint256 _buyAcapRate,
        uint256 _buyApadRate
    ) external onlyMultisig {
        require(_marketingRate <= 25, "_marketingRate cannot exceed 25%");
        require(_buyLotteryRate <= 100, "_lotteryRate cannot exceed 100%");
        require(_buyAcapRate <= 20, "_buyAcapRate cannot exceed 20%");
        require(_buyApadRate <= 20, "_buyApadRate cannot exceed 20%");
        require(
            _marketingRate + _buyLotteryRate + _buyAcapRate + _buyApadRate ==
                100,
            "the sum must be 100"
        );
        buyMarketingRate = _marketingRate;
        buyLotteryRate = _buyLotteryRate;
        buyAcapRate = _buyAcapRate;
        buyApadRate = _buyApadRate;
        emit SetBuyRate(
            _marketingRate,
            _buyLotteryRate,
            _buyAcapRate,
            _buyApadRate
        );
    }

    /// @notice Change the buy tax rate variables
    /// @param _minimumTax The minimum tax on buys
    /// @param _buyTaxRange The new range the buy tax is in [0 - _buyTaxRange]
    function setBuyTax(uint256 _minimumTax, uint256 _buyTaxRange)
        external
        onlyOwner
    {
        require(_minimumTax <= 20, "the minimum tax cannot exceed 20%");
        require(_buyTaxRange <= 20, "The buy tax range cannot exceed 20%");
        require(
            _minimumTax + _buyTaxRange <= 20,
            "The total tax on buys can never exceed 20 percent"
        );
        minimumBuyTax = _minimumTax;
        buyTaxRange = _buyTaxRange;
        emit SetBuyTax(_minimumTax, _buyTaxRange);
    }

    /// @notice Change the address of the lottery wallet
    /// @param _lotteryWallet The new address of the lottery wallet
    function setLotteryWallet(address payable _lotteryWallet)
        external
        onlyMultisig
    {
        require(
            _lotteryWallet != address(0),
            "new lottery wallet can not be the 0 address"
        );
        address _oldLotteryWallet = lotteryWallet;
        removeTaxExcluded(_oldLotteryWallet);
        lotteryWallet = _lotteryWallet;
        addTaxExcluded(_lotteryWallet);
        emit SetLotteryWallet(_oldLotteryWallet, _lotteryWallet);
    }

    /// @notice Change the address of the marketing wallet
    /// @param _marketingWallet The new address of the lottery wallet
    function setMarketingWallet(address payable _marketingWallet)
        external
        onlyOwner
    {
        require(
            _marketingWallet != address(0),
            "new lottery wallet can not be the 0 address"
        );
        address _oldMarketingWallet = marketingWallet;
        removeTaxExcluded(_oldMarketingWallet);
        marketingWallet = _marketingWallet;
        addTaxExcluded(_marketingWallet);
        emit SetMarketingWallet(_oldMarketingWallet, _marketingWallet);
    }

    /// @notice Change the marketing and lottery rate on sells
    /// @param _sellMarketingRate The new marketing tax rate
    /// @param _sellLotteryRate The new treasury tax rate
    function setSellRates(
        uint256 _sellMarketingRate,
        uint256 _sellLotteryRate,
        uint256 _sellAcapRate,
        uint256 _sellApadRate
    ) external onlyMultisig {
        require(_sellMarketingRate <= 25, "_marketingRate cannot exceed 25%");
        require(_sellLotteryRate <= 100, "_lotteryRate cannot exceed 100%");
        require(_sellAcapRate <= 20, "_sellAcapRate cannot exceed 20%");
        require(_sellApadRate <= 20, "_sellApadRate cannot exceed 20%");
        require(
            _sellMarketingRate +
                _sellLotteryRate +
                _sellAcapRate +
                _sellApadRate ==
                100,
            "the sum must be 100"
        );
        sellMarketingRate = _sellMarketingRate;
        sellLotteryRate = _sellLotteryRate;
        sellAcapRate = _sellAcapRate;
        sellApadRate = _sellApadRate;
        emit SetSellRates(
            _sellMarketingRate,
            _sellLotteryRate,
            _sellAcapRate,
            _sellApadRate
        );
    }

    /// @notice Change the sell tax rate variables
    /// @param _maximumSellTax The new minimum sell tax
    /// @param _maximumSellTaxRefund The new range the sell tax is in [0 - _sellTaxRange]
    function setSellTax(uint256 _maximumSellTax, uint256 _maximumSellTaxRefund)
        external
        onlyOwner
    {
        require(
            _maximumSellTax <= 25,
            "the maximum sell tax cannot exceed 25 percent"
        );
        require(
            _maximumSellTaxRefund <= _maximumSellTax,
            "The refund rate must be less than the maximum tax"
        );
        require(
            _maximumSellTax - _maximumSellTaxRefund <= 25,
            "The maximum effective sell tax can never exceed 25 percent"
        );
        maximumSellTax = _maximumSellTax;
        maximumSellTaxRefund = _maximumSellTaxRefund;
    }

    /// @notice Set the three different tax tiers by setting the highest bracket and the lower cutoff. Value multiplied by totalSupply divided by 10000. Example 50 = 5000000 tokens
    function setTaxTiers(uint256[] memory _taxTiers) external onlyOwner {
        require(
            _taxTiers.length == 2,
            "you have to give an array with 2 values"
        );
        taxTiers[0] = _taxTiers[0];
        taxTiers[1] = _taxTiers[1];
        emit SetTaxTiers(_taxTiers[0], _taxTiers[1]);
    }

    /// @notice Set the three different tax tier percentages
    function setTieredTaxPercentages(uint256[] memory _tieredPercentages)
        external
        onlyOwner
    {
        require(
            _tieredPercentages.length == 3,
            "you have to give an array with 3 values"
        );
        require(_tieredPercentages[0] <= 10);
        require(_tieredPercentages[1] == 10);
        require(_tieredPercentages[2] < 20);
        tieredTaxPercentage[0] = _tieredPercentages[0];
        tieredTaxPercentage[1] = _tieredPercentages[1];
        tieredTaxPercentage[2] = _tieredPercentages[2];
    }

    /// @notice Exclude an address from paying taxes
    /// @param account The address that we want to exclude from taxes
    function addTaxExcluded(address account) public onlyOwner {
        _taxExcluded[account] = true;
        emit AddTaxExcluded(account);
    }

    /// @notice Get if an account is excluded from paying taxes
    /// @param account The address that we want to get the value for
    /// @return taxExcluded Boolean that tells if an address has to pay taxes
    function isTaxExcluded(address account)
        public
        view
        returns (bool taxExcluded)
    {
        return _taxExcluded[account];
    }

    /// @notice Get a breakdown of send and tax amounts
    /// @param amount The amount to tax in wei
    /// @param user the address for which to generate a random number
    /// @return send The raw amount to send
    /// @return buyTax the tax percentage that the user pays on buy
    /// @return marketing The raw marketing tax amount
    /// @return lottery The raw lottery tax amount
    /// @return acap the raw acap tax amount
    /// @return apad the raw apad tax amount
    function _getBuyTaxInfo(uint256 amount, address user)
        internal
        view
        returns (
            uint256 send,
            uint256 buyTax,
            uint256 marketing,
            uint256 lottery,
            uint256 acap,
            uint256 apad
        )
    {
        uint256 _baseBuyTax = _getBuyTaxPercentage(amount, user);
        uint256 _multiplier = _getBuyTaxTier(amount);
        buyTax = _baseBuyTax.mul(_multiplier).div(10);
        uint256 _sendRate = 100 - (buyTax);
        send = amount.mul(_sendRate).div(100);
        uint256 _totalTax = amount.sub(send);
        marketing = _totalTax.mul(buyMarketingRate).div(100);
        lottery = _totalTax.mul(buyLotteryRate).div(100);
        acap = _totalTax.mul(buyAcapRate).div(100);
        apad = _totalTax.mul(buyApadRate).div(100);
    }

    /// @notice Get a breakdown of send and tax amounts
    /// @param amount The amount that is being seend
    /// @param user the address for which to generate a random number
    /// @return buyTaxPercentage
    function _getBuyTaxPercentage(uint256 amount, address user)
        internal
        view
        returns (uint256 buyTaxPercentage)
    {
        if (buyTaxRange > 0) {
            uint256 _randomNumber = _getPseudoRandomNumber(
                buyTaxRange,
                amount,
                user
            );
            return _randomNumber.add(minimumBuyTax);
        } else {
            return minimumBuyTax;
        }
    }

    /// @notice get the tier for the buy tax based on the amount of tokens bought
    /// @param amount the amount of tokens bought
    /// @return taxTier the multiplier that corresponds to the tax tier

    function _getBuyTaxTier(uint256 amount)
        internal
        view
        returns (uint256 taxTier)
    {
        if (amount > _totalSupply.mul(taxTiers[0]).div(10000)) {
            return tieredTaxPercentage[0];
        } else if (amount > _totalSupply.mul(taxTiers[1]).div(10000)) {
            return tieredTaxPercentage[1];
        } else return tieredTaxPercentage[2];
    }

    /// @notice Get a breakdown of send and tax amounts
    /// @param amount The amount that is being transfered.
    /// @param user the address for which to generate a random number
    /// @return send The raw amount to send
    /// @return totalTax the total taxes on the sell tx
    /// @return marketing The raw marketing tax amount
    /// @return lottery The raw lottery tax amount
    /// @return acap the raw acap tax amount
    /// @return apad the raw apad tax amount
    function _getSellTaxInfo(uint256 amount, address user)
        internal
        view
        returns (
            uint256 send,
            uint256 totalTax,
            uint256 marketing,
            uint256 lottery,
            uint256 acap,
            uint256 apad
        )
    {
        bool winner = _get0SellTaxWinner(amount, user);
        uint256 _sendRate;
        if (winner) {
            _sendRate = 100; //0 percent sell tax winner
        } else {
            uint256 _taxMultiplier = _getSellTaxTier(amount);
            uint256 _maximumTax = _taxMultiplier.mul(maximumSellTax).div(10);
            _sendRate = 100 - _maximumTax;
        }
        send = amount.mul(_sendRate).div(100);
        totalTax = amount.sub(send);
        marketing = totalTax.mul(sellMarketingRate).div(100);
        lottery = totalTax.mul(sellLotteryRate).div(100);
        acap = totalTax.mul(sellAcapRate).div(100);
        apad = totalTax.mul(sellApadRate).div(100);
    }

    /// @notice get the tier for the sell tax based on the amount of tokens bought
    /// @param amount the amount of tokens bought
    /// @return taxTier the multiplier that corresponds to the tax tier

    function _getSellTaxTier(uint256 amount)
        internal
        view
        returns (uint256 taxTier)
    {
        if (amount > _totalSupply.mul(taxTiers[0]).div(10000)) {
            return tieredTaxPercentage[2];
        } else if (amount > _totalSupply.mul(taxTiers[1]).div(10000)) {
            return tieredTaxPercentage[1];
        } else return tieredTaxPercentage[0];
    }

    /// @notice Get a breakdown of send and tax amounts
    /// @param amount the amount that is being send. Will be used to generate a more difficult pseudo random number
    /// @param user the address for which to generate a random number
    /// @return sellTaxPercentage
    function _getSellTaxPercentage(uint256 amount, address user)
        internal
        view
        returns (uint256 sellTaxPercentage)
    {
        if (maximumSellTaxRefund > 0) {
            uint256 _randomNumber = _getPseudoRandomNumber(100, amount, user);
            sellTaxPercentage = _randomNumber % maximumSellTaxRefund;
        } else {
            sellTaxPercentage = 0;
        }
        return sellTaxPercentage;
    }
}

File 22 of 27 : ILottery.sol
pragma solidity ^0.8.0;

interface ILottery {
    function getBalance(address staker) external view returns (uint256 balance);
}

File 23 of 27 : IPermissions.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity ^0.8.0;

interface IPermissions {
    function isWhitelisted(address user) external view returns (bool);

    function buyLimit(address user) external view returns (uint256);
}

File 24 of 27 : Multisig.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Context.sol";

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

    event MultisigTransferred(
        address indexed previousMultisig,
        address indexed newMultisig
    );

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

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

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newMultisig`).
     * Can only be called by the current multisig.
     */
    function transferMultisig(address newMultisig) public virtual onlyMultisig {
        require(
            newMultisig != address(0),
            "Multisig: new multisig is the zero address"
        );
        _transferMultisig(newMultisig);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newMultisig`).
     * Internal function without access restriction.
     */
    function _transferMultisig(address newMultisig) internal virtual {
        address oldMultisig = _multisig;
        _multisig = newMultisig;
        emit MultisigTransferred(oldMultisig, newMultisig);
    }
}

File 25 of 27 : SortitionSumTreeFactory.sol
/**
 *  @authors: [@epiqueras]
 *  @reviewers: [@clesaege, @unknownunknown1, @ferittuncer, @remedcu, @shalzz]
 *  @auditors: []
 *  @bounties: [{ duration: 28 days, link: https://github.com/kleros/kleros/issues/115, maxPayout: 50 ETH }]
 *  @deployments: [ https://etherscan.io/address/0x180eba68d164c3f8c3f6dc354125ebccf4dfcb86 ]
 */

pragma solidity ^0.8.0;

library SortitionSumTreeFactory {
    /* Structs */

    struct SortitionSumTree {
        uint256 K; // The maximum number of childs per node.
        // We use this to keep track of vacant positions in the tree after removing a leaf. This is for keeping the tree as balanced as possible without spending gas on moving nodes around.
        uint256[] stack;
        uint256[] nodes;
        // Two-way mapping of IDs to node indexes. Note that node index 0 is reserved for the root node, and means the ID does not have a node.
        mapping(bytes32 => uint256) IDsToNodeIndexes;
        mapping(uint256 => bytes32) nodeIndexesToIDs;
    }

    /* Storage */

    struct SortitionSumTrees {
        mapping(bytes32 => SortitionSumTree) sortitionSumTrees;
    }

    /* internal */

    /**
     *  @dev Create a sortition sum tree at the specified key.
     *  @param _key The key of the new tree.
     *  @param _K The number of children each node in the tree should have.
     */
    function createTree(
        SortitionSumTrees storage self,
        bytes32 _key,
        uint256 _K
    ) internal {
        SortitionSumTree storage tree = self.sortitionSumTrees[_key];
        require(tree.K == 0, "Tree already exists.");
        require(_K > 1, "K must be greater than one.");
        tree.K = _K;
        tree.stack = new uint256[](0);
        tree.nodes = new uint256[](0);
        tree.nodes.push(0);
    }

    /**
     *  @dev Set a value of a tree.
     *  @param _key The key of the tree.
     *  @param _value The new value.
     *  @param _ID The ID of the value.
     *  `O(log_k(n))` where
     *  `k` is the maximum number of childs per node in the tree,
     *   and `n` is the maximum number of nodes ever appended.
     */
    function set(
        SortitionSumTrees storage self,
        bytes32 _key,
        uint256 _value,
        bytes32 _ID
    ) internal {
        SortitionSumTree storage tree = self.sortitionSumTrees[_key];
        uint256 treeIndex = tree.IDsToNodeIndexes[_ID];

        if (treeIndex == 0) {
            // No existing node.
            if (_value != 0) {
                // Non zero value.
                // Append.
                // Add node.
                if (tree.stack.length == 0) {
                    // No vacant spots.
                    // Get the index and append the value.
                    treeIndex = tree.nodes.length;
                    tree.nodes.push(_value);

                    // Potentially append a new node and make the parent a sum node.
                    if (treeIndex != 1 && (treeIndex - 1) % tree.K == 0) {
                        // Is first child.
                        uint256 parentIndex = treeIndex / tree.K;
                        bytes32 parentID = tree.nodeIndexesToIDs[parentIndex];
                        uint256 newIndex = treeIndex + 1;
                        tree.nodes.push(tree.nodes[parentIndex]);
                        delete tree.nodeIndexesToIDs[parentIndex];
                        tree.IDsToNodeIndexes[parentID] = newIndex;
                        tree.nodeIndexesToIDs[newIndex] = parentID;
                    }
                } else {
                    // Some vacant spot.
                    // Pop the stack and append the value.
                    treeIndex = tree.stack[tree.stack.length - 1];
                    tree.stack.pop();
                    tree.nodes[treeIndex] = _value;
                }

                // Add label.
                tree.IDsToNodeIndexes[_ID] = treeIndex;
                tree.nodeIndexesToIDs[treeIndex] = _ID;

                updateParents(self, _key, treeIndex, true, _value);
            }
        } else {
            // Existing node.
            if (_value == 0) {
                // Zero value.
                // Remove.
                // Remember value and set to 0.
                uint256 value = tree.nodes[treeIndex];
                tree.nodes[treeIndex] = 0;

                // Push to stack.
                tree.stack.push(treeIndex);

                // Clear label.
                delete tree.IDsToNodeIndexes[_ID];
                delete tree.nodeIndexesToIDs[treeIndex];

                updateParents(self, _key, treeIndex, false, value);
            } else if (_value != tree.nodes[treeIndex]) {
                // New, non zero value.
                // Set.
                bool plusOrMinus = tree.nodes[treeIndex] <= _value;
                uint256 plusOrMinusValue = plusOrMinus
                    ? _value - tree.nodes[treeIndex]
                    : tree.nodes[treeIndex] - _value;
                tree.nodes[treeIndex] = _value;

                updateParents(
                    self,
                    _key,
                    treeIndex,
                    plusOrMinus,
                    plusOrMinusValue
                );
            }
        }
    }

    /* internal Views */

    /**
     *  @dev Query the leaves of a tree. Note that if `startIndex == 0`, the tree is empty and the root node will be returned.
     *  @param _key The key of the tree to get the leaves from.
     *  @param _cursor The pagination cursor.
     *  @param _count The number of items to return.
     *  @return startIndex The index at which leaves start
     *  @return values The values of the returned leaves
     *  @return hasMore Whether there are more for pagination.
     *  `O(n)` where
     *  `n` is the maximum number of nodes ever appended.
     */
    function queryLeafs(
        SortitionSumTrees storage self,
        bytes32 _key,
        uint256 _cursor,
        uint256 _count
    )
        internal
        view
        returns (
            uint256 startIndex,
            uint256[] memory values,
            bool hasMore
        )
    {
        SortitionSumTree storage tree = self.sortitionSumTrees[_key];

        // Find the start index.
        for (uint256 i = 0; i < tree.nodes.length; i++) {
            if ((tree.K * i) + 1 >= tree.nodes.length) {
                startIndex = i;
                break;
            }
        }

        // Get the values.
        uint256 loopStartIndex = startIndex + _cursor;
        values = new uint256[](
            loopStartIndex + _count > tree.nodes.length
                ? tree.nodes.length - loopStartIndex
                : _count
        );
        uint256 valuesIndex = 0;
        for (uint256 j = loopStartIndex; j < tree.nodes.length; j++) {
            if (valuesIndex < _count) {
                values[valuesIndex] = tree.nodes[j];
                valuesIndex++;
            } else {
                hasMore = true;
                break;
            }
        }
    }

    /**
     *  @dev Draw an ID from a tree using a number. Note that this function reverts if the sum of all values in the tree is 0.
     *  @param _key The key of the tree.
     *  @param _drawnNumber The drawn number.
     *  @return ID The drawn ID.
     *  `O(k * log_k(n))` where
     *  `k` is the maximum number of childs per node in the tree,
     *   and `n` is the maximum number of nodes ever appended.
     */
    function draw(
        SortitionSumTrees storage self,
        bytes32 _key,
        uint256 _drawnNumber
    ) internal view returns (bytes32 ID) {
        SortitionSumTree storage tree = self.sortitionSumTrees[_key];
        uint256 treeIndex = 0;
        uint256 currentDrawnNumber = _drawnNumber % tree.nodes[0];

        while (
            (tree.K * treeIndex) + 1 < tree.nodes.length // While it still has children.
        )
            for (uint256 i = 1; i <= tree.K; i++) {
                // Loop over children.
                uint256 nodeIndex = (tree.K * treeIndex) + i;
                uint256 nodeValue = tree.nodes[nodeIndex];

                if (currentDrawnNumber >= nodeValue)
                    currentDrawnNumber -= nodeValue; // Go to the next child.
                else {
                    // Pick this child.
                    treeIndex = nodeIndex;
                    break;
                }
            }

        ID = tree.nodeIndexesToIDs[treeIndex];
    }

    /** @dev Gets a specified ID's associated value.
     *  @param _key The key of the tree.
     *  @param _ID The ID of the value.
     *  @return value The associated value.
     */
    function stakeOf(
        SortitionSumTrees storage self,
        bytes32 _key,
        bytes32 _ID
    ) internal view returns (uint256 value) {
        SortitionSumTree storage tree = self.sortitionSumTrees[_key];
        uint256 treeIndex = tree.IDsToNodeIndexes[_ID];

        if (treeIndex == 0) value = 0;
        else value = tree.nodes[treeIndex];
    }

    function total(SortitionSumTrees storage self, bytes32 _key)
        internal
        view
        returns (uint256)
    {
        SortitionSumTree storage tree = self.sortitionSumTrees[_key];
        if (tree.nodes.length == 0) {
            return 0;
        } else {
            return tree.nodes[0];
        }
    }

    /* Private */

    /**
     *  @dev Update all the parents of a node.
     *  @param _key The key of the tree to update.
     *  @param _treeIndex The index of the node to start from.
     *  @param _plusOrMinus Wether to add (true) or substract (false).
     *  @param _value The value to add or substract.
     *  `O(log_k(n))` where
     *  `k` is the maximum number of childs per node in the tree,
     *   and `n` is the maximum number of nodes ever appended.
     */
    function updateParents(
        SortitionSumTrees storage self,
        bytes32 _key,
        uint256 _treeIndex,
        bool _plusOrMinus,
        uint256 _value
    ) private {
        SortitionSumTree storage tree = self.sortitionSumTrees[_key];

        uint256 parentIndex = _treeIndex;
        while (parentIndex != 0) {
            parentIndex = (parentIndex - 1) / tree.K;
            tree.nodes[parentIndex] = _plusOrMinus
                ? tree.nodes[parentIndex] + _value
                : tree.nodes[parentIndex] - _value;
        }
    }
}

File 26 of 27 : WinOnBuy.sol
//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract WinOnBuy is Ownable {
    using SafeMath for uint256;
    //Lottery
    bool public buyWinnersActive = false;
    uint256 public lastBuyAmount;
    uint256 public lastSellTax;
    //The secret number that is being used for buyorder winner and sell tax winner
    uint256 internal _secretNumber;
    //The winning chances for the different prizes
    uint256 public chanceToWinSellTax;
    uint256 public chanceToWinLastBuy;
    uint256 public chanceToWin0SellTax;
    uint256 public minimumBuyToWin = 500_000 ether;
    uint256 public totalWinners;
    uint256 public lastAmountWon;
    uint256 public totalTokensWon;
    address public lastBuyWinner;
    mapping(address => uint256) public amountWonOnBuy;
    mapping(address => bool) public won0SellTax;
    mapping(address => bool) public wonLastBuy; //to avoid that same wallet wins multiple times

    event SetBuyWinnersActive(bool buyWinnersActive);
    event SetMinBuyToWin(uint256 oldMinBuyToWin, uint256 newMinimumBuyToWin);
    event SetChanceToWinLastBuy(uint256 oldChanceToWin, uint256 newChanceToWin);
    event SetChanceToWinSellTax(uint256 oldChanceToWin, uint256 newChanceToWin);
    event SetChanceToWin0SellTax(
        uint256 oldChanceToWin,
        uint256 newChanceToWin
    );
    event LastBuyWinner(address indexed winner, uint256 indexed amountWon);
    event LastSellTaxWinner(address indexed winner, uint256 indexed amountWon);

    /// @notice Enables the possibility to win on buy
    function setBuyWinnersActive(bool _buyWinnersActive) external onlyOwner {
        require(
            buyWinnersActive != _buyWinnersActive,
            "New value is the same as current value"
        );
        buyWinnersActive = _buyWinnersActive;
        emit SetBuyWinnersActive(_buyWinnersActive);
    }

    /// @notice Change the minimum buy size to be elgible to win
    /// @param _minimumBuyToWin The new cooldown in seconds
    function setMinimumBuyToWin(uint256 _minimumBuyToWin) external onlyOwner {
        uint256 _oldMinBuy = minimumBuyToWin;
        minimumBuyToWin = _minimumBuyToWin;
        emit SetMinBuyToWin(_oldMinBuy, _minimumBuyToWin);
    }

    /// @notice Change the chance to win the amount of the last buy order (1/Chance)
    /// @param _chanceToWinLastBuy The new chance to win
    function setChanceToWinLastBuy(uint256 _chanceToWinLastBuy)
        public
        onlyOwner
    {
        require(
            _chanceToWinLastBuy >= 100,
            "_chanceToWinLastBuy must be greater than or equal to 100"
        );
        require(
            _chanceToWinLastBuy <= 500,
            "_chanceToWinLastBuy must be less than or equal to 500"
        );
        uint256 _oldChanceToWin = chanceToWinLastBuy;
        chanceToWinLastBuy = _chanceToWinLastBuy;
        emit SetChanceToWinLastBuy(_oldChanceToWin, _chanceToWinLastBuy);
    }

    /// @notice Change the chance to win the last sell tax (1/Chance)
    /// @param _chanceToWinSellTax The new chance to win the last paid sell tax
    function setChanceToWinSellTax(uint256 _chanceToWinSellTax)
        public
        onlyOwner
    {
        require(
            _chanceToWinSellTax >= 50,
            "_chanceToWinSellTax must be greater than or equal to 50"
        );
        require(
            _chanceToWinSellTax <= 200,
            "_chanceToWinSellTax must be less than or equal to 200"
        );
        uint256 _oldChanceToWin = chanceToWinSellTax;
        chanceToWinSellTax = _chanceToWinSellTax;
        emit SetChanceToWinSellTax(_oldChanceToWin, _chanceToWinSellTax);
    }

    /// @notice Change the chance to win the 0 sell tax (1/Chance)
    /// @param _chanceToWin0SellTax The new chance to win the last paid sell tax
    function setChanceToWin0SellTax(uint256 _chanceToWin0SellTax)
        public
        onlyOwner
    {
        require(
            _chanceToWin0SellTax >= 50,
            "_chanceToWin0SellTax must be greater than or equal to 50"
        );
        require(
            _chanceToWin0SellTax <= 200,
            "_chanceToWin0SellTax must be less than or equal to 200"
        );
        uint256 _oldChanceToWin = chanceToWin0SellTax;
        chanceToWin0SellTax = _chanceToWin0SellTax;
        emit SetChanceToWin0SellTax(_oldChanceToWin, _chanceToWin0SellTax);
    }

    /// @notice Returns a bool if the user wins 0 sell tax
    /// @param amount the amount that is being send. Will be used to generate a more difficult pseudo random number
    /// @param user the address for which to generate a random number
    /// @return boolean if the user has won
    function _get0SellTaxWinner(uint256 amount, address user)
        internal
        view
        returns (bool)
    {
        uint256 randomTxNumber = _getPseudoRandomNumber(
            chanceToWin0SellTax,
            amount,
            user
        );
        uint256 winningNumber = _secretNumber % chanceToWin0SellTax;
        return (winningNumber == randomTxNumber);
    }

    /// @notice Get a pseudo random number to define the tax on the transaction.
    /// @dev We can use a pseudo random number because the likelihood of gaming the random number is low because of the buy and sell tax and limited amount to be won
    /// @param chanceVariable The chance (1/Chance) to win a specific prize
    /// @return pseudoRandomNumber a pseudeo random number created from the keccak256 of the block timestamp, difficulty and msg.sender
    function _getPseudoRandomNumber(
        uint256 chanceVariable,
        uint256 amount,
        address user
    ) internal view returns (uint256 pseudoRandomNumber) {
        return
            uint256(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            block.timestamp + amount,
                            block.difficulty,
                            user
                        )
                    )
                )
            ).mod(chanceVariable);
    }
}

File 27 of 27 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_uniswapFactory","type":"address"},{"internalType":"address","name":"_uniswapRouter","type":"address"},{"internalType":"address payable","name":"_lotteryWallet","type":"address"},{"internalType":"address payable","name":"_marketingWallet","type":"address"},{"internalType":"address payable","name":"_apadWallet","type":"address"},{"internalType":"address payable","name":"_acapWallet","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"}],"name":"AddTaxExcluded","type":"event"},{"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":[{"indexed":false,"internalType":"bool","name":"tradingEnabled","type":"bool"}],"name":"EnableTrading","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"winner","type":"address"},{"indexed":true,"internalType":"uint256","name":"amountWon","type":"uint256"}],"name":"LastBuyWinner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"winner","type":"address"},{"indexed":true,"internalType":"uint256","name":"amountWon","type":"uint256"}],"name":"LastSellTaxWinner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousMultisig","type":"address"},{"indexed":true,"internalType":"address","name":"newMultisig","type":"address"}],"name":"MultisigTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousPermission","type":"address"},{"indexed":false,"internalType":"address","name":"nextPermission","type":"address"}],"name":"PermissionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"}],"name":"RemoveTaxExcluded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RescueLottery","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RescueMarketing","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"buyMarketingRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"buyLotteryRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"buyAcapRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"buyApadRate","type":"uint256"}],"name":"SetBuyRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minimumBuyTax","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"buyTaxRange","type":"uint256"}],"name":"SetBuyTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"buyWinnersActive","type":"bool"}],"name":"SetBuyWinnersActive","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChanceToWin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChanceToWin","type":"uint256"}],"name":"SetChanceToWin0SellTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChanceToWin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChanceToWin","type":"uint256"}],"name":"SetChanceToWinLastBuy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChanceToWin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChanceToWin","type":"uint256"}],"name":"SetChanceToWinSellTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCooldown","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCooldown","type":"uint256"}],"name":"SetCooldown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldLotteryWallet","type":"address"},{"indexed":false,"internalType":"address","name":"newLotteryWallet","type":"address"}],"name":"SetLotteryWallet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldMarketingWallet","type":"address"},{"indexed":false,"internalType":"address","name":"newMarketingWallet","type":"address"}],"name":"SetMarketingWallet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinBuyToWin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinimumBuyToWin","type":"uint256"}],"name":"SetMinBuyToWin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinTokenBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinTokenBalance","type":"uint256"}],"name":"SetMinTokenBalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sellMarketingRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sellLotteryRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sellAcapRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sellApadRate","type":"uint256"}],"name":"SetSellRates","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_maximumSellTax","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_maximumSellTaxRefund","type":"uint256"}],"name":"SetSellTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"newValue","type":"bool"}],"name":"SetSwapFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tier1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tier2","type":"uint256"}],"name":"SetTaxTiers","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"multiplier1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"multiplier2","type":"uint256"}],"name":"SetTieredTaxPercentages","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":true,"internalType":"address","name":"winner","type":"address"},{"indexed":false,"internalType":"bool","name":"won","type":"bool"}],"name":"Win0SellTax","type":"event"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_taxExcluded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acapWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addTaxExcluded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","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":"","type":"address"}],"name":"amountWonOnBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"apadWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyAcapRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyApadRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyLotteryRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyMarketingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyTaxRange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyWinnersActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chanceToWin0SellTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chanceToWinLastBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chanceToWinSellTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deadBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_deadBlocks","type":"uint256"}],"name":"enableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isTaxExcluded","outputs":[{"internalType":"bool","name":"taxExcluded","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastAmountWon","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBuyAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBuyWinner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSellTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lotteryWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumSellTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumSellTaxRefund","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumBuyTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumBuyToWin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"multisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permission","outputs":[{"internalType":"contract IPermissions","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeTaxExcluded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueLotteryTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueMarketingTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellAcapRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellApadRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellLotteryRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellMarketingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketingRate","type":"uint256"},{"internalType":"uint256","name":"_buyLotteryRate","type":"uint256"},{"internalType":"uint256","name":"_buyAcapRate","type":"uint256"},{"internalType":"uint256","name":"_buyApadRate","type":"uint256"}],"name":"setBuyRates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumTax","type":"uint256"},{"internalType":"uint256","name":"_buyTaxRange","type":"uint256"}],"name":"setBuyTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_buyWinnersActive","type":"bool"}],"name":"setBuyWinnersActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chanceToWin0SellTax","type":"uint256"}],"name":"setChanceToWin0SellTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chanceToWinLastBuy","type":"uint256"}],"name":"setChanceToWinLastBuy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chanceToWinSellTax","type":"uint256"}],"name":"setChanceToWinSellTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cooldown","type":"uint256"}],"name":"setCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_lotteryWallet","type":"address"}],"name":"setLotteryWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_marketingWallet","type":"address"}],"name":"setMarketingWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumBuyToWin","type":"uint256"}],"name":"setMinimumBuyToWin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minTokenBalance","type":"uint256"}],"name":"setMinimumTokenBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPermissions","name":"_permission","type":"address"}],"name":"setPermissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sellMarketingRate","type":"uint256"},{"internalType":"uint256","name":"_sellLotteryRate","type":"uint256"},{"internalType":"uint256","name":"_sellAcapRate","type":"uint256"},{"internalType":"uint256","name":"_sellApadRate","type":"uint256"}],"name":"setSellRates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maximumSellTax","type":"uint256"},{"internalType":"uint256","name":"_maximumSellTaxRefund","type":"uint256"}],"name":"setSellTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_swapFees","type":"bool"}],"name":"setSwapFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_taxTiers","type":"uint256[]"}],"name":"setTaxTiers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tieredPercentages","type":"uint256[]"}],"name":"setTieredTaxPercentages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"taxPercentagePaidByUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"taxTiers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tieredTaxPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAcap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalApad","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLottery","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMarketing","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":"totalTokensWon","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWinners","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":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMultisig","type":"address"}],"name":"transferMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"won0SellTax","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wonLastBuy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6005805460ff60a01b191690556969e10de76676d0800000600c9081556014601655603c60175560086018556019818155601e601a8190556032601b556004601c556010601d55919091556000601f81905560209190915560215560e0604052600a608081815260a082905260c0919091526200008190602290600362000b3e565b506040805180820190915260328152600a6020820152620000a790602390600262000b3e565b506a07d995ee4bd116c7400000603055603180546001600160a81b03191660011790556032805462ffffff60a01b191690556002603455602d603555348015620000f057600080fd5b5060405162005b8338038062005b83833981016040819052620001139162000c46565b604080518082018252600a815269527566666c6520496e7560b01b602080830191825283518085019094526006845265525546464c4560d01b908401528151919291620001639160039162000b93565b5080516200017990600490602084019062000b93565b50505062000196620001906200042160201b60201c565b62000425565b620001a13362000477565b620001be620001b86005546001600160a01b031690565b620004c9565b620001ca6000620004c9565b620001d584620004c9565b620001e082620004c9565b620001eb81620004c9565b620001f630620004c9565b6200020183620004c9565b6200020d606462000572565b6200021960c8620006f5565b62000225603262000872565b6200023d306b033b2e3c9fd0803ce8000000620009ee565b602880546001600160a01b03199081166001600160a01b0387811691909117909255602980548216868416179055602b80548216848416179055602a805490911684831617905560318054610100600160a81b03191661010088841681029190911791829055604080516315ab88c960e31b815290518a948581169463c9c6539694309491049091169163ad5c464891600480820192602092909190829003018186803b158015620002ee57600080fd5b505afa15801562000303573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000329919062000c27565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381600087803b1580156200037257600080fd5b505af115801562000387573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003ad919062000c27565b603280546001600160a01b03929092166001600160a01b031990921691909117905560408051426020820152449181019190915233606090811b6001600160601b0319169082015260740160408051601f1981840301815291905280516020909101206008555062000d5495505050505050565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b601480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f32911a2d59a9d4c952ec2065ce8e1f0ff57dc6c63e9e80e97cbe39a1c4d1254f90600090a35050565b6005546001600160a01b03163314620005185760405162461bcd60e51b8152602060048201819052602482015260008051602062005b6383398151915260448201526064015b60405180910390fd5b6001600160a01b0381166000818152602c6020908152604091829020805460ff1916600117905590519182527f77212386da25388bfec9dae62e05a7dc2d48eafa74f5a61fe2d281b7f523a2f8910160405180910390a150565b6005546001600160a01b03163314620005bd5760405162461bcd60e51b8152602060048201819052602482015260008051602062005b6383398151915260448201526064016200050f565b6032811015620006365760405162461bcd60e51b815260206004820152603760248201527f5f6368616e6365546f57696e53656c6c546178206d757374206265206772656160448201527f746572207468616e206f7220657175616c20746f20353000000000000000000060648201526084016200050f565b60c8811115620006af5760405162461bcd60e51b815260206004820152603560248201527f5f6368616e6365546f57696e53656c6c546178206d757374206265206c65737360448201527f207468616e206f7220657175616c20746f20323030000000000000000000000060648201526084016200050f565b600980549082905560408051828152602081018490527f7967308f951657e9cd1b4d70be1e6b6844ecdd6e5c275f8fcd283cd84ac179e991015b60405180910390a15050565b6005546001600160a01b03163314620007405760405162461bcd60e51b8152602060048201819052602482015260008051602062005b6383398151915260448201526064016200050f565b6064811015620007b95760405162461bcd60e51b815260206004820152603860248201527f5f6368616e6365546f57696e4c617374427579206d757374206265206772656160448201527f746572207468616e206f7220657175616c20746f20313030000000000000000060648201526084016200050f565b6101f4811115620008335760405162461bcd60e51b815260206004820152603560248201527f5f6368616e6365546f57696e4c617374427579206d757374206265206c65737360448201527f207468616e206f7220657175616c20746f20353030000000000000000000000060648201526084016200050f565b600a80549082905560408051828152602081018490527f6f2f49b106c8d88a973ecf1ba1606060c685572bdbbb63d5cfa403c0140106589101620006e9565b6005546001600160a01b03163314620008bd5760405162461bcd60e51b8152602060048201819052602482015260008051602062005b6383398151915260448201526064016200050f565b6032811015620009365760405162461bcd60e51b815260206004820152603860248201527f5f6368616e6365546f57696e3053656c6c546178206d7573742062652067726560448201527f61746572207468616e206f7220657175616c20746f203530000000000000000060648201526084016200050f565b60c8811115620009af5760405162461bcd60e51b815260206004820152603660248201527f5f6368616e6365546f57696e3053656c6c546178206d757374206265206c657360448201527f73207468616e206f7220657175616c20746f203230300000000000000000000060648201526084016200050f565b600b80549082905560408051828152602081018490527f3a20c80ad67871e7f099e47c8e0a5077e1b41a565c23ee01a964eaa886f77ba99101620006e9565b6b033b2e3c9fd0803ce800000062000a178260155462000ad760201b62002f441790919060201c565b111562000a675760405162461bcd60e51b815260206004820152601360248201527f4d617820737570706c792065786365656465640000000000000000000000000060448201526064016200050f565b62000a838160155462000ad760201b62002f441790919060201c565b60155562000a92828262000aec565b6040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600062000ae5828462000cd9565b9392505050565b6001600160a01b0382166000908152602e602090815260409091205462000b1e91839062002f4462000ad7821b17901c565b6001600160a01b039092166000908152602e602052604090209190915550565b82805482825590600052602060002090810192821562000b81579160200282015b8281111562000b81578251829060ff1690559160200191906001019062000b5f565b5062000b8f92915062000c10565b5090565b82805462000ba19062000cfe565b90600052602060002090601f01602090048101928262000bc5576000855562000b81565b82601f1062000be057805160ff191683800117855562000b81565b8280016001018555821562000b81579182015b8281111562000b8157825182559160200191906001019062000bf3565b5b8082111562000b8f576000815560010162000c11565b60006020828403121562000c39578081fd5b815162000ae58162000d3b565b60008060008060008060c0878903121562000c5f578182fd5b865162000c6c8162000d3b565b602088015190965062000c7f8162000d3b565b604088015190955062000c928162000d3b565b606088015190945062000ca58162000d3b565b608088015190935062000cb88162000d3b565b60a088015190925062000ccb8162000d3b565b809150509295509295509295565b6000821982111562000cf957634e487b7160e01b81526011600452602481fd5b500190565b600181811c9082168062000d1357607f821691505b6020821081141562000d3557634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038116811462000d5157600080fd5b50565b614dff8062000d646000396000f3fe6080604052600436106104fb5760003560e01c806382aa7c681161028c578063c04a90a41161015a578063e084d35a116100cc578063f3b0c8b711610085578063f3b0c8b714610ede578063f3c41d0414610efe578063f8b45b0514610f1e578063f9b7e14014610f3d578063fabb0b4f14610f6a578063fd76cb5014610f8057600080fd5b8063e084d35a14610e3c578063e32b4dea14610e52578063e3f9fc6314610e72578063ee40166e14610e92578063f13b7a6714610ea8578063f2fde38b14610ebe57600080fd5b8063ce745a0b1161011e578063ce745a0b14610d9a578063d011f66c14610dba578063d10f3fbc14610dda578063d5c6c5cc14610df0578063d91fddfc14610e06578063dd62ed3e14610e1c57600080fd5b8063c04a90a414610cf8578063c399d15614610d0e578063c703a3b014610d24578063c7673efc14610d54578063c94c79c614610d6a57600080fd5b8063a364b077116101fe578063b41356c9116101b7578063b41356c914610c51578063b44a109b14610c71578063b9ccf21d14610c91578063bbc0c74214610cab578063bcc941b614610ccc578063bd4b106214610ce257600080fd5b8063a364b07714610b8e578063a457c2d714610bae578063a9059cbb14610bce578063a906c70e14610bee578063a9988ee614610c0e578063afe9281f14610c2457600080fd5b80638da5cb5b116102505780638da5cb5b14610af057806392c4632e14610b0e57806395d89b4114610b2457806399de0e5c14610b395780639c35293014610b59578063a0ef91df14610b7957600080fd5b806382aa7c6814610a7957806386bbee0a14610a995780638af05b3814610aaf5780638b25a91b14610ac55780638d8f2adb14610adb57600080fd5b806344e526ae116103c95780635ec881be1161033b578063715018a6116102f4578063715018a6146109d85780637485d967146109ed57806375f0a87414610a03578063786564c414610a23578063787a08a614610a435780637cb80c9114610a5957600080fd5b80635ec881be1461090857806360635a241461091e578063672434821461093f57806369ec8e9c1461095f5780636d7948e21461099857806370a08231146109b857600080fd5b80634fc3f41a1161038d5780634fc3f41a1461086957806351c6590a1461088957806351ecfeae1461089c5780635b78f35f146108bc5780635d098b38146108d25780635d0fee8a146108f257600080fd5b806344e526ae146107d5578063456d28d9146107eb5780634783c35b1461080b5780634b25bbcc146108295780634fb0b7e71461084957600080fd5b8063247b912d1161046d578063395093511161042657806339509351146107125780633c23fa50146107325780633c253e37146107485780633daacfef146107685780633e9ffbea1461078857806343c77ff01461079d57600080fd5b8063247b912d146106505780632d46ebe6146106705780632ff9c145146106a0578063313ce567146106c057806332cb6b0c146106dc57806335bf1a6b146106fc57600080fd5b8063110a3b18116104bf578063110a3b18146105c45780631233d83a146105da57806317700f01146105f057806318160ddd1461060557806321fc342d1461061a57806323b872dd1461063057600080fd5b80630331f37a1461050757806305a1f36d146105295780630696533e1461054957806306fdde0314610572578063095ea7b31461059457600080fd5b3661050257005b600080fd5b34801561051357600080fd5b506105276105223660046149e9565b610fa0565b005b34801561053557600080fd5b50610527610544366004614a3d565b611100565b34801561055557600080fd5b5061055f60165481565b6040519081526020015b60405180910390f35b34801561057e57600080fd5b50610587611296565b6040516105699190614abc565b3480156105a057600080fd5b506105b46105af366004614890565b611328565b6040519015158152602001610569565b3480156105d057600080fd5b5061055f601d5481565b3480156105e657600080fd5b5061055f60245481565b3480156105fc57600080fd5b50610527611342565b34801561061157600080fd5b5060155461055f565b34801561062657600080fd5b5061055f60095481565b34801561063c57600080fd5b506105b461064b366004614850565b6113c5565b34801561065c57600080fd5b5061052761066b366004614a3d565b6113e9565b34801561067c57600080fd5b506105b461068b3660046147e0565b60126020526000908152604090205460ff1681565b3480156106ac57600080fd5b506105276106bb3660046149e9565b61156f565b3480156106cc57600080fd5b5060405160128152602001610569565b3480156106e857600080fd5b5061055f6b033b2e3c9fd0803ce800000081565b34801561070857600080fd5b5061055f600c5481565b34801561071e57600080fd5b506105b461072d366004614890565b611657565b34801561073e57600080fd5b5061055f600e5481565b34801561075457600080fd5b506105276107633660046149e9565b611679565b34801561077457600080fd5b50610527610783366004614a19565b6116e1565b34801561079457600080fd5b506105276117cc565b3480156107a957600080fd5b50602a546107bd906001600160a01b031681565b6040516001600160a01b039091168152602001610569565b3480156107e157600080fd5b5061055f60065481565b3480156107f757600080fd5b506105276108063660046147e0565b61183c565b34801561081757600080fd5b506014546001600160a01b03166107bd565b34801561083557600080fd5b5061052761084436600461497e565b6118cf565b34801561085557600080fd5b506105276108643660046147e0565b611aa1565b34801561087557600080fd5b506105276108843660046149e9565b611b1f565b6105276108973660046149e9565b611b87565b3480156108a857600080fd5b506105276108b7366004614a8b565b611cc0565b3480156108c857600080fd5b5061055f60305481565b3480156108de57600080fd5b506105276108ed3660046147e0565b611ef6565b3480156108fe57600080fd5b5061055f60075481565b34801561091457600080fd5b5061055f60195481565b34801561092a57600080fd5b506005546105b490600160a01b900460ff1681565b34801561094b57600080fd5b5061052761095a3660046148bb565b611fbf565b34801561096b57600080fd5b506105b461097a3660046147e0565b6001600160a01b03166000908152602c602052604090205460ff1690565b3480156109a457600080fd5b5061055f6109b33660046149e9565b6120b6565b3480156109c457600080fd5b5061055f6109d33660046147e0565b6120d7565b3480156109e457600080fd5b506105276120f2565b3480156109f957600080fd5b5061055f601f5481565b348015610a0f57600080fd5b506029546107bd906001600160a01b031681565b348015610a2f57600080fd5b50610527610a3e366004614a8b565b612128565b348015610a4f57600080fd5b5061055f60355481565b348015610a6557600080fd5b50610527610a743660046149b1565b612354565b348015610a8557600080fd5b50610527610a943660046149e9565b61243b565b348015610aa557600080fd5b5061055f60265481565b348015610abb57600080fd5b5061055f60275481565b348015610ad157600080fd5b5061055f600b5481565b348015610ae757600080fd5b506105276124c9565b348015610afc57600080fd5b506005546001600160a01b03166107bd565b348015610b1a57600080fd5b5061055f600f5481565b348015610b3057600080fd5b50610587612506565b348015610b4557600080fd5b50610527610b5436600461497e565b612515565b348015610b6557600080fd5b50610527610b743660046147e0565b61274c565b348015610b8557600080fd5b50610527612815565b348015610b9a57600080fd5b506028546107bd906001600160a01b031681565b348015610bba57600080fd5b506105b4610bc9366004614890565b612878565b348015610bda57600080fd5b506105b4610be9366004614890565b6128f3565b348015610bfa57600080fd5b5061055f610c093660046149e9565b612901565b348015610c1a57600080fd5b5061055f601b5481565b348015610c3057600080fd5b5061055f610c3f3660046147e0565b602d6020526000908152604090205481565b348015610c5d57600080fd5b50610527610c6c3660046147e0565b612911565b348015610c7d57600080fd5b50610527610c8c366004614a19565b6129f4565b348015610c9d57600080fd5b506031546105b49060ff1681565b348015610cb757600080fd5b506032546105b490600160b01b900460ff1681565b348015610cd857600080fd5b5061055f600d5481565b348015610cee57600080fd5b5061055f60175481565b348015610d0457600080fd5b5061055f60205481565b348015610d1a57600080fd5b5061055f601a5481565b348015610d3057600080fd5b506105b4610d3f3660046147e0565b602c6020526000908152604090205460ff1681565b348015610d6057600080fd5b5061055f60215481565b348015610d7657600080fd5b506105b4610d853660046147e0565b60136020526000908152604090205460ff1681565b348015610da657600080fd5b506010546107bd906001600160a01b031681565b348015610dc657600080fd5b50610527610dd53660046147e0565b612add565b348015610de657600080fd5b5061055f601e5481565b348015610dfc57600080fd5b5061055f60255481565b348015610e1257600080fd5b5061055f601c5481565b348015610e2857600080fd5b5061055f610e37366004614818565b612b79565b348015610e4857600080fd5b5061055f60185481565b348015610e5e57600080fd5b50610527610e6d3660046149e9565b612ba4565b348015610e7e57600080fd5b50610527610e8d3660046149b1565b612cf2565b348015610e9e57600080fd5b5061055f60335481565b348015610eb457600080fd5b5061055f600a5481565b348015610eca57600080fd5b50610527610ed93660046147e0565b612d5d565b348015610eea57600080fd5b506036546107bd906001600160a01b031681565b348015610f0a57600080fd5b50602b546107bd906001600160a01b031681565b348015610f2a57600080fd5b5061055f6a084595161401484a00000081565b348015610f4957600080fd5b5061055f610f583660046147e0565b60116020526000908152604090205481565b348015610f7657600080fd5b5061055f60345481565b348015610f8c57600080fd5b50610527610f9b3660046149e9565b612df5565b6005546001600160a01b03163314610fd35760405162461bcd60e51b8152600401610fca90614b9e565b60405180910390fd5b606481101561104a5760405162461bcd60e51b815260206004820152603860248201527f5f6368616e6365546f57696e4c617374427579206d757374206265206772656160448201527f746572207468616e206f7220657175616c20746f2031303000000000000000006064820152608401610fca565b6101f48111156110ba5760405162461bcd60e51b815260206004820152603560248201527f5f6368616e6365546f57696e4c617374427579206d757374206265206c6573736044820152740207468616e206f7220657175616c20746f2035303605c1b6064820152608401610fca565b600a80549082905560408051828152602081018490527f6f2f49b106c8d88a973ecf1ba1606060c685572bdbbb63d5cfa403c01401065891015b60405180910390a15050565b6005546001600160a01b0316331461112a5760405162461bcd60e51b8152600401610fca90614b9e565b60148211156111855760405162461bcd60e51b815260206004820152602160248201527f746865206d696e696d756d207461782063616e6e6f74206578636565642032306044820152602560f81b6064820152608401610fca565b60148111156111e25760405162461bcd60e51b815260206004820152602360248201527f54686520627579207461782072616e67652063616e6e6f74206578636565642060448201526232302560e81b6064820152608401610fca565b60146111ee8284614c98565b11156112565760405162461bcd60e51b815260206004820152603160248201527f54686520746f74616c20746178206f6e20627579732063616e206e6576657220604482015270195e18d95959080c8c081c195c98d95b9d607a1b6064820152608401610fca565b601e829055601f81905560408051838152602081018390527f95afa6180501e4c61695d81f1c1096289d31a5dec7b4323b3e1e72dd1726839b91016110f4565b6060600380546112a590614cfa565b80601f01602080910402602001604051908101604052809291908181526020018280546112d190614cfa565b801561131e5780601f106112f35761010080835404028352916020019161131e565b820191906000526020600020905b81548152906001019060200180831161130157829003601f168201915b5050505050905090565b600033611336818585612f57565b60019150505b92915050565b6005546001600160a01b0316331461136c5760405162461bcd60e51b8152600401610fca90614b9e565b603254600160b01b900460ff1661138257600080fd5b6032805460ff60b01b19169055604051600081527f94ceecefa8cebcfa143903429574e20ce9424e1e52abaf30db6548b7995696509060200160405180910390a1565b6000336113d385828561307b565b6113de8585856130f5565b506001949350505050565b6005546001600160a01b031633146114135760405162461bcd60e51b8152600401610fca90614b9e565b601982111561147a5760405162461bcd60e51b815260206004820152602d60248201527f746865206d6178696d756d2073656c6c207461782063616e6e6f74206578636560448201526c1959080c8d481c195c98d95b9d609a1b6064820152608401610fca565b818111156114e45760405162461bcd60e51b815260206004820152603160248201527f54686520726566756e642072617465206d757374206265206c657373207468616044820152700dc40e8d0ca40dac2f0d2daeada40e8c2f607b1b6064820152608401610fca565b60196114f08284614ce3565b11156115645760405162461bcd60e51b815260206004820152603a60248201527f546865206d6178696d756d206566666563746976652073656c6c20746178206360448201527f616e206e65766572206578636565642032352070657263656e740000000000006064820152608401610fca565b602091909155602155565b6005546001600160a01b031633146115995760405162461bcd60e51b8152600401610fca90614b9e565b6a084595161401484a00000081106116195760405162461bcd60e51b815260206004820152603a60248201527f746865206d696e696d756d20746f6b656e2062616c616e63652063616e6e6f7460448201527f2065786365656420746865206d6178696d756d2077616c6c65740000000000006064820152608401610fca565b603080549082905560408051828152602081018490527f78063f7bb2e8c4cce8ad7cf028c22749216dda9f2d6ee749c546454b19f29e6691016110f4565b60003361133681858561166a8383612b79565b6116749190614c98565b612f57565b6005546001600160a01b031633146116a35760405162461bcd60e51b8152600401610fca90614b9e565b600c80549082905560408051828152602081018490527f06c6269cc2982245f20d3bd9cea048281744d60d99787ae851052e812f52e31a91016110f4565b6014546001600160a01b0316331461170b5760405162461bcd60e51b8152600401610fca90614b5a565b6024548211156117725760405162461bcd60e51b815260206004820152602c60248201527f416d6f756e742063616e6e6f742062652067726561746572207468616e20746f60448201526b74616c4d61726b6574696e6760a01b6064820152608401610fca565b61177d3082846135d3565b60245461178a9083613743565b602455604080516001600160a01b0383168152602081018490527fc0c03ef822240d250825b8497afdd17584b1a486ea39678af4af61be03f1a10b91016110f4565b6005546001600160a01b031633146117f65760405162461bcd60e51b8152600401610fca90614b9e565b6000611801306120d7565b603254909150600160a01b900460ff1661183957600061182c6030548361374390919063ffffffff16565b90506118378161374f565b505b50565b6005546001600160a01b031633146118665760405162461bcd60e51b8152600401610fca90614b9e565b603654604080516001600160a01b03928316815291831660208301527f77bba246501572ee45df8e0c0a86ffe9f8bb680bf26c87d51aade002912afe60910160405180910390a1603680546001600160a01b0319166001600160a01b0392909216919091179055565b6005546001600160a01b031633146118f95760405162461bcd60e51b8152600401610fca90614b9e565b805160021461195a5760405162461bcd60e51b815260206004820152602760248201527f796f75206861766520746f206769766520616e206172726179207769746820326044820152662076616c75657360c81b6064820152608401610fca565b8060008151811061197b57634e487b7160e01b600052603260045260246000fd5b602002602001015160236000815481106119a557634e487b7160e01b600052603260045260246000fd5b9060005260206000200181905550806001815181106119d457634e487b7160e01b600052603260045260246000fd5b602002602001015160236001815481106119fe57634e487b7160e01b600052603260045260246000fd5b90600052602060002001819055507f09be53297890c8127c2a943487297b09d22dfc8b5944e26a8396cb83582d72bf81600081518110611a4e57634e487b7160e01b600052603260045260246000fd5b602002602001015182600181518110611a7757634e487b7160e01b600052603260045260246000fd5b6020026020010151604051611a96929190918252602082015260400190565b60405180910390a150565b6005546001600160a01b03163314611acb5760405162461bcd60e51b8152600401610fca90614b9e565b6001600160a01b0381166000818152602c6020908152604091829020805460ff1916600117905590519182527f77212386da25388bfec9dae62e05a7dc2d48eafa74f5a61fe2d281b7f523a2f89101611a96565b6005546001600160a01b03163314611b495760405162461bcd60e51b8152600401610fca90614b9e565b603580549082905560408051828152602081018490527f645f52ef8686d35868b88d34001e51066af1866ccd3a09d6c4dd86d9237fa24f91016110f4565b6005546001600160a01b03163314611bb15760405162461bcd60e51b8152600401610fca90614b9e565b6032805460ff60a81b1916600160a81b179055603154611be29030906001600160a01b036101009091041683612f57565b6031546001600160a01b036101009091041663f305d719343084600080611c116005546001600160a01b031690565b60405160e088901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094526044840192909252606483015290911660848201524260a482015260c4016060604051808303818588803b158015611c7457600080fd5b505af1158015611c88573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611cad9190614a5e565b50506032805460ff60a81b191690555050565b6014546001600160a01b03163314611cea5760405162461bcd60e51b8152600401610fca90614b5a565b6019841115611d3b5760405162461bcd60e51b815260206004820181905260248201527f5f6d61726b6574696e67526174652063616e6e6f7420657863656564203235256044820152606401610fca565b6064831115611d8c5760405162461bcd60e51b815260206004820152601f60248201527f5f6c6f7474657279526174652063616e6e6f74206578636565642031303025006044820152606401610fca565b6014821115611ddd5760405162461bcd60e51b815260206004820152601e60248201527f5f62757941636170526174652063616e6e6f74206578636565642032302500006044820152606401610fca565b6014811115611e2e5760405162461bcd60e51b815260206004820152601e60248201527f5f62757941706164526174652063616e6e6f74206578636565642032302500006044820152606401610fca565b8082611e3a8587614c98565b611e449190614c98565b611e4e9190614c98565b606414611e935760405162461bcd60e51b815260206004820152601360248201527207468652073756d206d7573742062652031303606c1b6044820152606401610fca565b60168490556017839055601882905560198190556040805185815260208101859052908101839052606081018290527fcf9db2bbd258468326ac79ea233ce92f45c982e1b6bd9c4d03485cca40e00452906080015b60405180910390a150505050565b6005546001600160a01b03163314611f205760405162461bcd60e51b8152600401610fca90614b9e565b6001600160a01b038116611f465760405162461bcd60e51b8152600401610fca90614b0f565b6029546001600160a01b0316611f5b81612911565b602980546001600160a01b0319166001600160a01b038416179055611f7f82611aa1565b604080516001600160a01b038084168252841660208201527f83e9b0264f846c733d721fc222bd1b60d47f257c00f2c8ee812d03d29fa87a6491016110f4565b6005546001600160a01b03163314611fe95760405162461bcd60e51b8152600401610fca90614b9e565b805182511461203a5760405162461bcd60e51b815260206004820152601860248201527f6172726179206c656e67746873206d757374206d6174636800000000000000006044820152606401610fca565b60005b82518110156120b15761209f3084838151811061206a57634e487b7160e01b600052603260045260246000fd5b602002602001015184848151811061209257634e487b7160e01b600052603260045260246000fd5b60200260200101516135d3565b806120a981614d35565b91505061203d565b505050565b602281815481106120c657600080fd5b600091825260209091200154905081565b6001600160a01b03166000908152602e602052604090205490565b6005546001600160a01b0316331461211c5760405162461bcd60e51b8152600401610fca90614b9e565b6121266000613b97565b565b6014546001600160a01b031633146121525760405162461bcd60e51b8152600401610fca90614b5a565b60198411156121a35760405162461bcd60e51b815260206004820181905260248201527f5f6d61726b6574696e67526174652063616e6e6f7420657863656564203235256044820152606401610fca565b60648311156121f45760405162461bcd60e51b815260206004820152601f60248201527f5f6c6f7474657279526174652063616e6e6f74206578636565642031303025006044820152606401610fca565b60148211156122455760405162461bcd60e51b815260206004820152601f60248201527f5f73656c6c41636170526174652063616e6e6f742065786365656420323025006044820152606401610fca565b60148111156122965760405162461bcd60e51b815260206004820152601f60248201527f5f73656c6c41706164526174652063616e6e6f742065786365656420323025006044820152606401610fca565b80826122a28587614c98565b6122ac9190614c98565b6122b69190614c98565b6064146122fb5760405162461bcd60e51b815260206004820152601360248201527207468652073756d206d7573742062652031303606c1b6044820152606401610fca565b601a849055601b839055601c829055601d8190556040805185815260208101859052908101839052606081018290527fbf2a0c734d68fd8490304294767942f9417a94f2834edaa62fecf9c76abb076890608001611ee8565b6005546001600160a01b0316331461237e5760405162461bcd60e51b8152600401610fca90614b9e565b60055460ff600160a01b90910416151581151514156123ee5760405162461bcd60e51b815260206004820152602660248201527f4e65772076616c7565206973207468652073616d652061732063757272656e746044820152652076616c756560d01b6064820152608401610fca565b60058054821515600160a01b0260ff60a01b199091161790556040517f1ab42d691b06b8b4e813592bf56d49d16a096d1aeb3963aec49ace70bbf2d00b90611a9690831515815260200190565b6005546001600160a01b031633146124655760405162461bcd60e51b8152600401610fca90614b9e565b603254600160b01b900460ff161561247c57600080fd5b6032805460ff60b01b1916600160b01b179055436033556034819055604051600181527f94ceecefa8cebcfa143903429574e20ce9424e1e52abaf30db6548b79956965090602001611a96565b6014546001600160a01b031633146124f35760405162461bcd60e51b8152600401610fca90614b5a565b6121263033612501306120d7565b6135d3565b6060600480546112a590614cfa565b6005546001600160a01b0316331461253f5760405162461bcd60e51b8152600401610fca90614b9e565b80516003146125a05760405162461bcd60e51b815260206004820152602760248201527f796f75206861766520746f206769766520616e206172726179207769746820336044820152662076616c75657360c81b6064820152608401610fca565b600a816000815181106125c357634e487b7160e01b600052603260045260246000fd5b602002602001015111156125d657600080fd5b806001815181106125f757634e487b7160e01b600052603260045260246000fd5b6020026020010151600a1461260b57600080fd5b60148160028151811061262e57634e487b7160e01b600052603260045260246000fd5b60200260200101511061264057600080fd5b8060008151811061266157634e487b7160e01b600052603260045260246000fd5b6020026020010151602260008154811061268b57634e487b7160e01b600052603260045260246000fd5b9060005260206000200181905550806001815181106126ba57634e487b7160e01b600052603260045260246000fd5b602002602001015160226001815481106126e457634e487b7160e01b600052603260045260246000fd5b90600052602060002001819055508060028151811061271357634e487b7160e01b600052603260045260246000fd5b6020026020010151602260028154811061273d57634e487b7160e01b600052603260045260246000fd5b60009182526020909120015550565b6014546001600160a01b031633146127765760405162461bcd60e51b8152600401610fca90614b5a565b6001600160a01b03811661279c5760405162461bcd60e51b8152600401610fca90614b0f565b6028546001600160a01b03166127b181612911565b602880546001600160a01b0319166001600160a01b0384161790556127d582611aa1565b604080516001600160a01b038084168252841660208201527f92d34bee85fbb3471c4fe1be9001a7268755ff43b8f32a9471a3f78c41c2ac7791016110f4565b6014546001600160a01b0316331461283f5760405162461bcd60e51b8152600401610fca90614b5a565b6005546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015611839573d6000803e3d6000fd5b600033816128868286612b79565b9050838110156128e65760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610fca565b6113de8286868403612f57565b6000336113368185856130f5565b602381815481106120c657600080fd5b6005546001600160a01b0316331461293b5760405162461bcd60e51b8152600401610fca90614b9e565b6001600160a01b0381166000908152602c602052604090205460ff166129a35760405162461bcd60e51b815260206004820152601c60248201527f4163636f756e74206d757374206e6f74206265206578636c75646564000000006044820152606401610fca565b6001600160a01b0381166000818152602c6020908152604091829020805460ff1916905590519182527f5411747049e49a4928cc1f7614fce69f0eeb03028d8b5e6751954194541dae119101611a96565b6014546001600160a01b03163314612a1e5760405162461bcd60e51b8152600401610fca90614b5a565b602554821115612a835760405162461bcd60e51b815260206004820152602a60248201527f416d6f756e742063616e6e6f742062652067726561746572207468616e20746f60448201526974616c4c6f747465727960b01b6064820152608401610fca565b612a8e3082846135d3565b602554612a9b9083613743565b602555604080516001600160a01b0383168152602081018490527f3a98fb46769dfe100b30c1da7304246859fd7c1b2e09bd8f3127e8cf2605265b91016110f4565b6014546001600160a01b03163314612b075760405162461bcd60e51b8152600401610fca90614b5a565b6001600160a01b038116612b705760405162461bcd60e51b815260206004820152602a60248201527f4d756c74697369673a206e6577206d756c746973696720697320746865207a65604482015269726f206164647265737360b01b6064820152608401610fca565b61183981613be9565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6005546001600160a01b03163314612bce5760405162461bcd60e51b8152600401610fca90614b9e565b6032811015612c455760405162461bcd60e51b815260206004820152603760248201527f5f6368616e6365546f57696e53656c6c546178206d757374206265206772656160448201527f746572207468616e206f7220657175616c20746f2035300000000000000000006064820152608401610fca565b60c8811115612cb45760405162461bcd60e51b815260206004820152603560248201527f5f6368616e6365546f57696e53656c6c546178206d757374206265206c6573736044820152740207468616e206f7220657175616c20746f2032303605c1b6064820152608401610fca565b600980549082905560408051828152602081018490527f7967308f951657e9cd1b4d70be1e6b6844ecdd6e5c275f8fcd283cd84ac179e991016110f4565b6005546001600160a01b03163314612d1c5760405162461bcd60e51b8152600401610fca90614b9e565b6031805460ff19168215159081179091556040519081527fbc352061858700daa9e6a46cdc7c38889a043586646c8468eefb223756fd354290602001611a96565b6005546001600160a01b03163314612d875760405162461bcd60e51b8152600401610fca90614b9e565b6001600160a01b038116612dec5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610fca565b61183981613b97565b6005546001600160a01b03163314612e1f5760405162461bcd60e51b8152600401610fca90614b9e565b6032811015612e965760405162461bcd60e51b815260206004820152603860248201527f5f6368616e6365546f57696e3053656c6c546178206d7573742062652067726560448201527f61746572207468616e206f7220657175616c20746f20353000000000000000006064820152608401610fca565b60c8811115612f065760405162461bcd60e51b815260206004820152603660248201527f5f6368616e6365546f57696e3053656c6c546178206d757374206265206c6573604482015275073207468616e206f7220657175616c20746f203230360541b6064820152608401610fca565b600b80549082905560408051828152602081018490527f3a20c80ad67871e7f099e47c8e0a5077e1b41a565c23ee01a964eaa886f77ba991016110f4565b6000612f508284614c98565b9392505050565b6001600160a01b038316612fb95760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610fca565b6001600160a01b03821661301a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610fca565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006130878484612b79565b905060001981146130ef57818110156130e25760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610fca565b6130ef8484848403612f57565b50505050565b6001600160a01b0383166000908152602c602052604090205460ff168061313457506001600160a01b0382166000908152602c602052604090205460ff165b15613144576120b18383836135d3565b600061314f306120d7565b603054603254919250821015906001600160a01b0386811691161480159061318557506032546001600160a01b03858116911614155b156132b35760285460405163f8b2cb4f60e01b81526001600160a01b038681166004830152600092169063f8b2cb4f9060240160206040518083038186803b1580156131d057600080fd5b505afa1580156131e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132089190614a01565b90506a084595161401484a0000006132338261322d613226896120d7565b8890612f44565b90612f44565b106132a65760405162461bcd60e51b815260206004820152603a60248201527f74686520726563697069656e742063616e6e6f74206f776e206d6f726520746860448201527f616e20312070657263656e74206f6620616c6c20746f6b656e730000000000006064820152608401610fca565b6132b18686866135d3565b505b8080156132ca5750603254600160a01b900460ff16155b80156132e457506032546001600160a01b03868116911614155b80156132f2575060315460ff165b15613314576000603054836133079190614ce3565b90506133128161374f565b505b6036546001600160a01b0316156134af57603654604051633af32abf60e01b81526001600160a01b03868116600483015290911690633af32abf9060240160206040518083038186803b15801561336a57600080fd5b505afa15801561337e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a291906149cd565b6133ee5760405162461bcd60e51b815260206004820152601e60248201527f55736572206973206e6f742077686974656c697374656420746f2062757900006044820152606401610fca565b60365460405163409e64c160e11b81526001600160a01b0386811660048301529091169063813cc9829060240160206040518083038186803b15801561343357600080fd5b505afa158015613447573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061346b9190614a01565b8311156134af5760405162461bcd60e51b8152602060048201526012602482015271109d5e481b1a5b5a5d08195e18d95959195960721b6044820152606401610fca565b603254600160b01b900460ff166135085760405162461bcd60e51b815260206004820152601960248201527f54726164696e67206973206e6f742079657420616374697665000000000000006044820152606401610fca565b6032546001600160a01b03868116911614156135ab576035541561359b576035546001600160a01b0385166000908152602f6020526040902054429161354d91614c98565b111561359b5760405162461bcd60e51b815260206004820152601860248201527f436f6f6c646f776e206973207374696c6c2061637469766500000000000000006044820152606401610fca565b6135a6858585613c3b565b6135cc565b6032546001600160a01b03858116911614156135cc576135cc858585613eab565b5050505050565b6001600160a01b0383166136295760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610fca565b6001600160a01b03821661367f5760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f2061646472657373000000006044820152606401610fca565b600061368a846120d7565b9050818110156136dc5760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e6365006044820152606401610fca565b6136e68483613fd8565b6136f0838361401b565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161373591815260200190565b60405180910390a350505050565b6000612f508284614ce3565b6032805460ff60a01b1916600160a01b17905560408051600280825260608201835260009260208301908036833701905050905030816000815181106137a557634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050603160019054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b15801561381357600080fd5b505afa158015613827573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384b91906147fc565b8160018151811061386c57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03928316602091820292909201015260315461389791309161010090041684612f57565b60315460405163791ac94760e01b8152479161010090046001600160a01b03169063791ac947906138d5908690600090879030904290600401614bd3565b600060405180830381600087803b1580156138ef57600080fd5b505af1158015613903573d6000803e3d6000fd5b50505050600061391c824761374390919063ffffffff16565b9050600061394360265461322d60275461322d602554602454612f4490919063ffffffff16565b90506000613966826139606024548961403e90919063ffffffff16565b9061404a565b90506000613983836139606025548a61403e90919063ffffffff16565b905060006139a0846139606027548b61403e90919063ffffffff16565b905060006139bd856139606026548c61403e90919063ffffffff16565b905060006139da866139606024548a61403e90919063ffffffff16565b905060006139f7876139606025548b61403e90919063ffffffff16565b90506000613a14886139606027548c61403e90919063ffffffff16565b90506000613a31896139606026548d61403e90919063ffffffff16565b90508315613a75576029546040516001600160a01b039091169085156108fc029086906000818181858888f19350505050158015613a73573d6000803e3d6000fd5b505b8215613ab7576028546040516001600160a01b039091169084156108fc029085906000818181858888f19350505050158015613ab5573d6000803e3d6000fd5b505b8115613af957602b546040516001600160a01b039091169083156108fc029084906000818181858888f19350505050158015613af7573d6000803e3d6000fd5b505b8015613b3b57602a546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015613b39573d6000803e3d6000fd5b505b602454613b489089613743565b602455602554613b589088613743565b602555602754613b689087613743565b602755602654613b789086613743565b60265550506032805460ff60a01b191690555050505050505050505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b601480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f32911a2d59a9d4c952ec2065ce8e1f0ff57dc6c63e9e80e97cbe39a1c4d1254f90600090a35050565b80600080808080613c4c8689614056565b6001600160a01b038e166000908152602d60205260409020859055600554959b50929950909750955093509150600160a01b900460ff168015613c915750600c548710155b15613d56576000613ca3898989614137565b905060006025548211613cb7575080613cbc565b506025545b613cc7308b836135d3565b602554613cd49082613743565b6025556001600160a01b038a1660009081526011602052604081208054839290613cff908490614c98565b90915550508015613d53576001600d6000828254613d1d9190614c98565b9091555050600e819055600f54613d349082612f44565b600f55601080546001600160a01b0319166001600160a01b038c161790555b50505b60285460405163f8b2cb4f60e01b81526001600160a01b038a811660048301526a084595161401484a00000092613df69291169063f8b2cb4f9060240160206040518083038186803b158015613dab57600080fd5b505afa158015613dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613de39190614a01565b61322d613def8c6120d7565b8a90612f44565b1115613e6a5760405162461bcd60e51b815260206004820152603b60248201527f796f752063616e6e6f74206f776e206d6f7265207468616e203120706572636560448201527f6e74206f662074686520746f6b656e73207065722077616c6c657400000000006064820152608401610fca565b613e758989886135d3565b613e828986868686614234565b5050506006939093555050506001600160a01b03166000908152602f6020526040902042905550565b80600080808080613ebc86896142f1565b949a5091985096509094509250905082613f5a576001600160a01b0389166000908152601260205260409020805460ff19166001179055613efe8989886135d3565b6001600d6000828254613f119190614c98565b9091555050604051600181526001600160a01b038a16907f3ea6aeb2e34388609f28505d9c8e2c2ceac13b6e8ae54882da102c4bf2eaa71b9060200160405180910390a2613fcd565b613f658989886135d3565b613f728986868585614234565b6000613f7e888a6143ec565b90506000613f916064613960848c61403e565b90506025548111613fca57613fa68582613743565b600755602554613fb69082613743565b6025558015613fca57613fca308b836135d3565b50505b505050505050505050565b6001600160a01b0382166000908152602e6020526040902054613ffb9082613743565b6001600160a01b039092166000908152602e602052604090209190915550565b6001600160a01b0382166000908152602e6020526040902054613ffb9082612f44565b6000612f508284614cc4565b6000612f508284614cb0565b600080600080600080600061406b8989614426565b905060006140788a614460565b9050614089600a613960848461403e565b96506000614098886064614ce3565b90506140a960646139608d8461403e565b985060006140b78c8b613743565b90506140d360646139606016548461403e90919063ffffffff16565b97506140ef60646139606017548461403e90919063ffffffff16565b965061410b60646139606018548461403e90919063ffffffff16565b955061412760646139606019548461403e90919063ffffffff16565b9450505050509295509295509295565b600080614147600a54848761455a565b90506000614158600954858861455a565b90506000614173600a546008546145bc90919063ffffffff16565b9050600061418e6009546008546145bc90919063ffffffff16565b9050600061419c89886145c8565b9050600083861480156141c857506001600160a01b038a1660009081526013602052604090205460ff16155b1561420a5781600654116141df57506006546141e2565b50805b6001600160a01b038a166000908152601360205260409020805460ff19166001179055614227565b828514156142275781600754116142245750600754614227565b50805b9998505050505050505050565b6001600160a01b03851661428a5760405162461bcd60e51b815260206004820152601e60248201527f7461786174696f6e2066726f6d20746865207a65726f206164647265737300006044820152606401610fca565b600061429c8261322d85818989612f44565b90506142a98630836135d3565b6024546142b69086612f44565b6024556025546142c69085612f44565b6025556027546142d69084612f44565b6027556026546142e69083612f44565b602655505050505050565b60008060008060008060006143068989614675565b90506000811561431857506064614353565b60006143238b6146a5565b90506000614341600a6139606020548561403e90919063ffffffff16565b905061434e816064614ce3565b925050505b61436260646139608c8461403e565b975061436e8a89613743565b965061438a6064613960601a548a61403e90919063ffffffff16565b95506143a66064613960601b548a61403e90919063ffffffff16565b94506143c26064613960601c548a61403e90919063ffffffff16565b93506143de6064613960601d548a61403e90919063ffffffff16565b925050509295509295509295565b6021546000901561441d5760006144056064858561455a565b9050602154816144159190614d50565b91505061133c565b50600092915050565b601f5460009015614457576000614440601f54858561455a565b9050614415601e5482612f4490919063ffffffff16565b50601e5461133c565b60006144a9612710613960602360008154811061448d57634e487b7160e01b600052603260045260246000fd5b906000526020600020015460155461403e90919063ffffffff16565b8211156144e45760226000815481106144d257634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b61450f612710613960602360018154811061448d57634e487b7160e01b600052603260045260246000fd5b8211156145385760226001815481106144d257634e487b7160e01b600052603260045260246000fd5b60226002815481106144d257634e487b7160e01b600052603260045260246000fd5b60006145b48461456a8542614c98565b6040805160208101929092524490820152606085811b6bffffffffffffffffffffffff19169082015260740160408051601f198184030181529190528051602090910120906145bc565b949350505050565b6000612f508284614d50565b60285460405163f8b2cb4f60e01b81526001600160a01b03848116600483015260009283926145b4929091169063f8b2cb4f9060240160206040518083038186803b15801561461657600080fd5b505afa15801561462a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061464e9190614a01565b61466f61465a876120d7565b61466f6a084595161401484a00000088613743565b90613743565b600080614685600b54858561455a565b90506000600b546008546146999190614d50565b91909114949350505050565b60006146d2612710613960602360008154811061448d57634e487b7160e01b600052603260045260246000fd5b8211156146fb5760226002815481106144d257634e487b7160e01b600052603260045260246000fd5b614726612710613960602360018154811061448d57634e487b7160e01b600052603260045260246000fd5b82111561474f5760226001815481106144d257634e487b7160e01b600052603260045260246000fd5b60226000815481106144d257634e487b7160e01b600052603260045260246000fd5b600082601f830112614781578081fd5b8135602061479661479183614c74565b614c43565b80838252828201915082860187848660051b89010111156147b5578586fd5b855b858110156147d3578135845292840192908401906001016147b7565b5090979650505050505050565b6000602082840312156147f1578081fd5b8135612f5081614da6565b60006020828403121561480d578081fd5b8151612f5081614da6565b6000806040838503121561482a578081fd5b823561483581614da6565b9150602083013561484581614da6565b809150509250929050565b600080600060608486031215614864578081fd5b833561486f81614da6565b9250602084013561487f81614da6565b929592945050506040919091013590565b600080604083850312156148a2578182fd5b82356148ad81614da6565b946020939093013593505050565b600080604083850312156148cd578182fd5b823567ffffffffffffffff808211156148e4578384fd5b818501915085601f8301126148f7578384fd5b8135602061490761479183614c74565b8083825282820191508286018a848660051b8901011115614926578889fd5b8896505b8487101561495157803561493d81614da6565b83526001969096019591830191830161492a565b5096505086013592505080821115614967578283fd5b5061497485828601614771565b9150509250929050565b60006020828403121561498f578081fd5b813567ffffffffffffffff8111156149a5578182fd5b6145b484828501614771565b6000602082840312156149c2578081fd5b8135612f5081614dbb565b6000602082840312156149de578081fd5b8151612f5081614dbb565b6000602082840312156149fa578081fd5b5035919050565b600060208284031215614a12578081fd5b5051919050565b60008060408385031215614a2b578081fd5b82359150602083013561484581614da6565b60008060408385031215614a4f578182fd5b50508035926020909101359150565b600080600060608486031215614a72578081fd5b8351925060208401519150604084015190509250925092565b60008060008060808587031215614aa0578182fd5b5050823594602084013594506040840135936060013592509050565b6000602080835283518082850152825b81811015614ae857858101830151858201604001528201614acc565b81811115614af95783604083870101525b50601f01601f1916929092016040019392505050565b6020808252602b908201527f6e6577206c6f74746572792077616c6c65742063616e206e6f7420626520746860408201526a652030206164647265737360a81b606082015260800190565b60208082526024908201527f4d756c74697369673a2063616c6c6572206973206e6f7420746865206d756c746040820152636973696760e01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b81811015614c225784516001600160a01b031683529383019391830191600101614bfd565b50506001600160a01b03969096166060850152505050608001529392505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715614c6c57614c6c614d90565b604052919050565b600067ffffffffffffffff821115614c8e57614c8e614d90565b5060051b60200190565b60008219821115614cab57614cab614d64565b500190565b600082614cbf57614cbf614d7a565b500490565b6000816000190483118215151615614cde57614cde614d64565b500290565b600082821015614cf557614cf5614d64565b500390565b600181811c90821680614d0e57607f821691505b60208210811415614d2f57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614d4957614d49614d64565b5060010190565b600082614d5f57614d5f614d7a565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461183957600080fd5b801515811461183957600080fdfea2646970667358221220653ac46376a51b582f060bf8737a7ff28da844094d98d4f467543c650358041d64736f6c634300080400334f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65720000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000065408355ffe5a612e7246b8e96ec8f3a3b3d06fc000000000000000000000000f5d1f84b5c0ab6e5024fce5d40f2acf2ad9ee99f0000000000000000000000001f58c7ae4c0cd8c91b64d0dc5b88a8ea121b3c4e000000000000000000000000f914bbdff49fd4ba1a1cbfc740e0d60a8674f438

Deployed Bytecode

0x6080604052600436106104fb5760003560e01c806382aa7c681161028c578063c04a90a41161015a578063e084d35a116100cc578063f3b0c8b711610085578063f3b0c8b714610ede578063f3c41d0414610efe578063f8b45b0514610f1e578063f9b7e14014610f3d578063fabb0b4f14610f6a578063fd76cb5014610f8057600080fd5b8063e084d35a14610e3c578063e32b4dea14610e52578063e3f9fc6314610e72578063ee40166e14610e92578063f13b7a6714610ea8578063f2fde38b14610ebe57600080fd5b8063ce745a0b1161011e578063ce745a0b14610d9a578063d011f66c14610dba578063d10f3fbc14610dda578063d5c6c5cc14610df0578063d91fddfc14610e06578063dd62ed3e14610e1c57600080fd5b8063c04a90a414610cf8578063c399d15614610d0e578063c703a3b014610d24578063c7673efc14610d54578063c94c79c614610d6a57600080fd5b8063a364b077116101fe578063b41356c9116101b7578063b41356c914610c51578063b44a109b14610c71578063b9ccf21d14610c91578063bbc0c74214610cab578063bcc941b614610ccc578063bd4b106214610ce257600080fd5b8063a364b07714610b8e578063a457c2d714610bae578063a9059cbb14610bce578063a906c70e14610bee578063a9988ee614610c0e578063afe9281f14610c2457600080fd5b80638da5cb5b116102505780638da5cb5b14610af057806392c4632e14610b0e57806395d89b4114610b2457806399de0e5c14610b395780639c35293014610b59578063a0ef91df14610b7957600080fd5b806382aa7c6814610a7957806386bbee0a14610a995780638af05b3814610aaf5780638b25a91b14610ac55780638d8f2adb14610adb57600080fd5b806344e526ae116103c95780635ec881be1161033b578063715018a6116102f4578063715018a6146109d85780637485d967146109ed57806375f0a87414610a03578063786564c414610a23578063787a08a614610a435780637cb80c9114610a5957600080fd5b80635ec881be1461090857806360635a241461091e578063672434821461093f57806369ec8e9c1461095f5780636d7948e21461099857806370a08231146109b857600080fd5b80634fc3f41a1161038d5780634fc3f41a1461086957806351c6590a1461088957806351ecfeae1461089c5780635b78f35f146108bc5780635d098b38146108d25780635d0fee8a146108f257600080fd5b806344e526ae146107d5578063456d28d9146107eb5780634783c35b1461080b5780634b25bbcc146108295780634fb0b7e71461084957600080fd5b8063247b912d1161046d578063395093511161042657806339509351146107125780633c23fa50146107325780633c253e37146107485780633daacfef146107685780633e9ffbea1461078857806343c77ff01461079d57600080fd5b8063247b912d146106505780632d46ebe6146106705780632ff9c145146106a0578063313ce567146106c057806332cb6b0c146106dc57806335bf1a6b146106fc57600080fd5b8063110a3b18116104bf578063110a3b18146105c45780631233d83a146105da57806317700f01146105f057806318160ddd1461060557806321fc342d1461061a57806323b872dd1461063057600080fd5b80630331f37a1461050757806305a1f36d146105295780630696533e1461054957806306fdde0314610572578063095ea7b31461059457600080fd5b3661050257005b600080fd5b34801561051357600080fd5b506105276105223660046149e9565b610fa0565b005b34801561053557600080fd5b50610527610544366004614a3d565b611100565b34801561055557600080fd5b5061055f60165481565b6040519081526020015b60405180910390f35b34801561057e57600080fd5b50610587611296565b6040516105699190614abc565b3480156105a057600080fd5b506105b46105af366004614890565b611328565b6040519015158152602001610569565b3480156105d057600080fd5b5061055f601d5481565b3480156105e657600080fd5b5061055f60245481565b3480156105fc57600080fd5b50610527611342565b34801561061157600080fd5b5060155461055f565b34801561062657600080fd5b5061055f60095481565b34801561063c57600080fd5b506105b461064b366004614850565b6113c5565b34801561065c57600080fd5b5061052761066b366004614a3d565b6113e9565b34801561067c57600080fd5b506105b461068b3660046147e0565b60126020526000908152604090205460ff1681565b3480156106ac57600080fd5b506105276106bb3660046149e9565b61156f565b3480156106cc57600080fd5b5060405160128152602001610569565b3480156106e857600080fd5b5061055f6b033b2e3c9fd0803ce800000081565b34801561070857600080fd5b5061055f600c5481565b34801561071e57600080fd5b506105b461072d366004614890565b611657565b34801561073e57600080fd5b5061055f600e5481565b34801561075457600080fd5b506105276107633660046149e9565b611679565b34801561077457600080fd5b50610527610783366004614a19565b6116e1565b34801561079457600080fd5b506105276117cc565b3480156107a957600080fd5b50602a546107bd906001600160a01b031681565b6040516001600160a01b039091168152602001610569565b3480156107e157600080fd5b5061055f60065481565b3480156107f757600080fd5b506105276108063660046147e0565b61183c565b34801561081757600080fd5b506014546001600160a01b03166107bd565b34801561083557600080fd5b5061052761084436600461497e565b6118cf565b34801561085557600080fd5b506105276108643660046147e0565b611aa1565b34801561087557600080fd5b506105276108843660046149e9565b611b1f565b6105276108973660046149e9565b611b87565b3480156108a857600080fd5b506105276108b7366004614a8b565b611cc0565b3480156108c857600080fd5b5061055f60305481565b3480156108de57600080fd5b506105276108ed3660046147e0565b611ef6565b3480156108fe57600080fd5b5061055f60075481565b34801561091457600080fd5b5061055f60195481565b34801561092a57600080fd5b506005546105b490600160a01b900460ff1681565b34801561094b57600080fd5b5061052761095a3660046148bb565b611fbf565b34801561096b57600080fd5b506105b461097a3660046147e0565b6001600160a01b03166000908152602c602052604090205460ff1690565b3480156109a457600080fd5b5061055f6109b33660046149e9565b6120b6565b3480156109c457600080fd5b5061055f6109d33660046147e0565b6120d7565b3480156109e457600080fd5b506105276120f2565b3480156109f957600080fd5b5061055f601f5481565b348015610a0f57600080fd5b506029546107bd906001600160a01b031681565b348015610a2f57600080fd5b50610527610a3e366004614a8b565b612128565b348015610a4f57600080fd5b5061055f60355481565b348015610a6557600080fd5b50610527610a743660046149b1565b612354565b348015610a8557600080fd5b50610527610a943660046149e9565b61243b565b348015610aa557600080fd5b5061055f60265481565b348015610abb57600080fd5b5061055f60275481565b348015610ad157600080fd5b5061055f600b5481565b348015610ae757600080fd5b506105276124c9565b348015610afc57600080fd5b506005546001600160a01b03166107bd565b348015610b1a57600080fd5b5061055f600f5481565b348015610b3057600080fd5b50610587612506565b348015610b4557600080fd5b50610527610b5436600461497e565b612515565b348015610b6557600080fd5b50610527610b743660046147e0565b61274c565b348015610b8557600080fd5b50610527612815565b348015610b9a57600080fd5b506028546107bd906001600160a01b031681565b348015610bba57600080fd5b506105b4610bc9366004614890565b612878565b348015610bda57600080fd5b506105b4610be9366004614890565b6128f3565b348015610bfa57600080fd5b5061055f610c093660046149e9565b612901565b348015610c1a57600080fd5b5061055f601b5481565b348015610c3057600080fd5b5061055f610c3f3660046147e0565b602d6020526000908152604090205481565b348015610c5d57600080fd5b50610527610c6c3660046147e0565b612911565b348015610c7d57600080fd5b50610527610c8c366004614a19565b6129f4565b348015610c9d57600080fd5b506031546105b49060ff1681565b348015610cb757600080fd5b506032546105b490600160b01b900460ff1681565b348015610cd857600080fd5b5061055f600d5481565b348015610cee57600080fd5b5061055f60175481565b348015610d0457600080fd5b5061055f60205481565b348015610d1a57600080fd5b5061055f601a5481565b348015610d3057600080fd5b506105b4610d3f3660046147e0565b602c6020526000908152604090205460ff1681565b348015610d6057600080fd5b5061055f60215481565b348015610d7657600080fd5b506105b4610d853660046147e0565b60136020526000908152604090205460ff1681565b348015610da657600080fd5b506010546107bd906001600160a01b031681565b348015610dc657600080fd5b50610527610dd53660046147e0565b612add565b348015610de657600080fd5b5061055f601e5481565b348015610dfc57600080fd5b5061055f60255481565b348015610e1257600080fd5b5061055f601c5481565b348015610e2857600080fd5b5061055f610e37366004614818565b612b79565b348015610e4857600080fd5b5061055f60185481565b348015610e5e57600080fd5b50610527610e6d3660046149e9565b612ba4565b348015610e7e57600080fd5b50610527610e8d3660046149b1565b612cf2565b348015610e9e57600080fd5b5061055f60335481565b348015610eb457600080fd5b5061055f600a5481565b348015610eca57600080fd5b50610527610ed93660046147e0565b612d5d565b348015610eea57600080fd5b506036546107bd906001600160a01b031681565b348015610f0a57600080fd5b50602b546107bd906001600160a01b031681565b348015610f2a57600080fd5b5061055f6a084595161401484a00000081565b348015610f4957600080fd5b5061055f610f583660046147e0565b60116020526000908152604090205481565b348015610f7657600080fd5b5061055f60345481565b348015610f8c57600080fd5b50610527610f9b3660046149e9565b612df5565b6005546001600160a01b03163314610fd35760405162461bcd60e51b8152600401610fca90614b9e565b60405180910390fd5b606481101561104a5760405162461bcd60e51b815260206004820152603860248201527f5f6368616e6365546f57696e4c617374427579206d757374206265206772656160448201527f746572207468616e206f7220657175616c20746f2031303000000000000000006064820152608401610fca565b6101f48111156110ba5760405162461bcd60e51b815260206004820152603560248201527f5f6368616e6365546f57696e4c617374427579206d757374206265206c6573736044820152740207468616e206f7220657175616c20746f2035303605c1b6064820152608401610fca565b600a80549082905560408051828152602081018490527f6f2f49b106c8d88a973ecf1ba1606060c685572bdbbb63d5cfa403c01401065891015b60405180910390a15050565b6005546001600160a01b0316331461112a5760405162461bcd60e51b8152600401610fca90614b9e565b60148211156111855760405162461bcd60e51b815260206004820152602160248201527f746865206d696e696d756d207461782063616e6e6f74206578636565642032306044820152602560f81b6064820152608401610fca565b60148111156111e25760405162461bcd60e51b815260206004820152602360248201527f54686520627579207461782072616e67652063616e6e6f74206578636565642060448201526232302560e81b6064820152608401610fca565b60146111ee8284614c98565b11156112565760405162461bcd60e51b815260206004820152603160248201527f54686520746f74616c20746178206f6e20627579732063616e206e6576657220604482015270195e18d95959080c8c081c195c98d95b9d607a1b6064820152608401610fca565b601e829055601f81905560408051838152602081018390527f95afa6180501e4c61695d81f1c1096289d31a5dec7b4323b3e1e72dd1726839b91016110f4565b6060600380546112a590614cfa565b80601f01602080910402602001604051908101604052809291908181526020018280546112d190614cfa565b801561131e5780601f106112f35761010080835404028352916020019161131e565b820191906000526020600020905b81548152906001019060200180831161130157829003601f168201915b5050505050905090565b600033611336818585612f57565b60019150505b92915050565b6005546001600160a01b0316331461136c5760405162461bcd60e51b8152600401610fca90614b9e565b603254600160b01b900460ff1661138257600080fd5b6032805460ff60b01b19169055604051600081527f94ceecefa8cebcfa143903429574e20ce9424e1e52abaf30db6548b7995696509060200160405180910390a1565b6000336113d385828561307b565b6113de8585856130f5565b506001949350505050565b6005546001600160a01b031633146114135760405162461bcd60e51b8152600401610fca90614b9e565b601982111561147a5760405162461bcd60e51b815260206004820152602d60248201527f746865206d6178696d756d2073656c6c207461782063616e6e6f74206578636560448201526c1959080c8d481c195c98d95b9d609a1b6064820152608401610fca565b818111156114e45760405162461bcd60e51b815260206004820152603160248201527f54686520726566756e642072617465206d757374206265206c657373207468616044820152700dc40e8d0ca40dac2f0d2daeada40e8c2f607b1b6064820152608401610fca565b60196114f08284614ce3565b11156115645760405162461bcd60e51b815260206004820152603a60248201527f546865206d6178696d756d206566666563746976652073656c6c20746178206360448201527f616e206e65766572206578636565642032352070657263656e740000000000006064820152608401610fca565b602091909155602155565b6005546001600160a01b031633146115995760405162461bcd60e51b8152600401610fca90614b9e565b6a084595161401484a00000081106116195760405162461bcd60e51b815260206004820152603a60248201527f746865206d696e696d756d20746f6b656e2062616c616e63652063616e6e6f7460448201527f2065786365656420746865206d6178696d756d2077616c6c65740000000000006064820152608401610fca565b603080549082905560408051828152602081018490527f78063f7bb2e8c4cce8ad7cf028c22749216dda9f2d6ee749c546454b19f29e6691016110f4565b60003361133681858561166a8383612b79565b6116749190614c98565b612f57565b6005546001600160a01b031633146116a35760405162461bcd60e51b8152600401610fca90614b9e565b600c80549082905560408051828152602081018490527f06c6269cc2982245f20d3bd9cea048281744d60d99787ae851052e812f52e31a91016110f4565b6014546001600160a01b0316331461170b5760405162461bcd60e51b8152600401610fca90614b5a565b6024548211156117725760405162461bcd60e51b815260206004820152602c60248201527f416d6f756e742063616e6e6f742062652067726561746572207468616e20746f60448201526b74616c4d61726b6574696e6760a01b6064820152608401610fca565b61177d3082846135d3565b60245461178a9083613743565b602455604080516001600160a01b0383168152602081018490527fc0c03ef822240d250825b8497afdd17584b1a486ea39678af4af61be03f1a10b91016110f4565b6005546001600160a01b031633146117f65760405162461bcd60e51b8152600401610fca90614b9e565b6000611801306120d7565b603254909150600160a01b900460ff1661183957600061182c6030548361374390919063ffffffff16565b90506118378161374f565b505b50565b6005546001600160a01b031633146118665760405162461bcd60e51b8152600401610fca90614b9e565b603654604080516001600160a01b03928316815291831660208301527f77bba246501572ee45df8e0c0a86ffe9f8bb680bf26c87d51aade002912afe60910160405180910390a1603680546001600160a01b0319166001600160a01b0392909216919091179055565b6005546001600160a01b031633146118f95760405162461bcd60e51b8152600401610fca90614b9e565b805160021461195a5760405162461bcd60e51b815260206004820152602760248201527f796f75206861766520746f206769766520616e206172726179207769746820326044820152662076616c75657360c81b6064820152608401610fca565b8060008151811061197b57634e487b7160e01b600052603260045260246000fd5b602002602001015160236000815481106119a557634e487b7160e01b600052603260045260246000fd5b9060005260206000200181905550806001815181106119d457634e487b7160e01b600052603260045260246000fd5b602002602001015160236001815481106119fe57634e487b7160e01b600052603260045260246000fd5b90600052602060002001819055507f09be53297890c8127c2a943487297b09d22dfc8b5944e26a8396cb83582d72bf81600081518110611a4e57634e487b7160e01b600052603260045260246000fd5b602002602001015182600181518110611a7757634e487b7160e01b600052603260045260246000fd5b6020026020010151604051611a96929190918252602082015260400190565b60405180910390a150565b6005546001600160a01b03163314611acb5760405162461bcd60e51b8152600401610fca90614b9e565b6001600160a01b0381166000818152602c6020908152604091829020805460ff1916600117905590519182527f77212386da25388bfec9dae62e05a7dc2d48eafa74f5a61fe2d281b7f523a2f89101611a96565b6005546001600160a01b03163314611b495760405162461bcd60e51b8152600401610fca90614b9e565b603580549082905560408051828152602081018490527f645f52ef8686d35868b88d34001e51066af1866ccd3a09d6c4dd86d9237fa24f91016110f4565b6005546001600160a01b03163314611bb15760405162461bcd60e51b8152600401610fca90614b9e565b6032805460ff60a81b1916600160a81b179055603154611be29030906001600160a01b036101009091041683612f57565b6031546001600160a01b036101009091041663f305d719343084600080611c116005546001600160a01b031690565b60405160e088901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094526044840192909252606483015290911660848201524260a482015260c4016060604051808303818588803b158015611c7457600080fd5b505af1158015611c88573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611cad9190614a5e565b50506032805460ff60a81b191690555050565b6014546001600160a01b03163314611cea5760405162461bcd60e51b8152600401610fca90614b5a565b6019841115611d3b5760405162461bcd60e51b815260206004820181905260248201527f5f6d61726b6574696e67526174652063616e6e6f7420657863656564203235256044820152606401610fca565b6064831115611d8c5760405162461bcd60e51b815260206004820152601f60248201527f5f6c6f7474657279526174652063616e6e6f74206578636565642031303025006044820152606401610fca565b6014821115611ddd5760405162461bcd60e51b815260206004820152601e60248201527f5f62757941636170526174652063616e6e6f74206578636565642032302500006044820152606401610fca565b6014811115611e2e5760405162461bcd60e51b815260206004820152601e60248201527f5f62757941706164526174652063616e6e6f74206578636565642032302500006044820152606401610fca565b8082611e3a8587614c98565b611e449190614c98565b611e4e9190614c98565b606414611e935760405162461bcd60e51b815260206004820152601360248201527207468652073756d206d7573742062652031303606c1b6044820152606401610fca565b60168490556017839055601882905560198190556040805185815260208101859052908101839052606081018290527fcf9db2bbd258468326ac79ea233ce92f45c982e1b6bd9c4d03485cca40e00452906080015b60405180910390a150505050565b6005546001600160a01b03163314611f205760405162461bcd60e51b8152600401610fca90614b9e565b6001600160a01b038116611f465760405162461bcd60e51b8152600401610fca90614b0f565b6029546001600160a01b0316611f5b81612911565b602980546001600160a01b0319166001600160a01b038416179055611f7f82611aa1565b604080516001600160a01b038084168252841660208201527f83e9b0264f846c733d721fc222bd1b60d47f257c00f2c8ee812d03d29fa87a6491016110f4565b6005546001600160a01b03163314611fe95760405162461bcd60e51b8152600401610fca90614b9e565b805182511461203a5760405162461bcd60e51b815260206004820152601860248201527f6172726179206c656e67746873206d757374206d6174636800000000000000006044820152606401610fca565b60005b82518110156120b15761209f3084838151811061206a57634e487b7160e01b600052603260045260246000fd5b602002602001015184848151811061209257634e487b7160e01b600052603260045260246000fd5b60200260200101516135d3565b806120a981614d35565b91505061203d565b505050565b602281815481106120c657600080fd5b600091825260209091200154905081565b6001600160a01b03166000908152602e602052604090205490565b6005546001600160a01b0316331461211c5760405162461bcd60e51b8152600401610fca90614b9e565b6121266000613b97565b565b6014546001600160a01b031633146121525760405162461bcd60e51b8152600401610fca90614b5a565b60198411156121a35760405162461bcd60e51b815260206004820181905260248201527f5f6d61726b6574696e67526174652063616e6e6f7420657863656564203235256044820152606401610fca565b60648311156121f45760405162461bcd60e51b815260206004820152601f60248201527f5f6c6f7474657279526174652063616e6e6f74206578636565642031303025006044820152606401610fca565b60148211156122455760405162461bcd60e51b815260206004820152601f60248201527f5f73656c6c41636170526174652063616e6e6f742065786365656420323025006044820152606401610fca565b60148111156122965760405162461bcd60e51b815260206004820152601f60248201527f5f73656c6c41706164526174652063616e6e6f742065786365656420323025006044820152606401610fca565b80826122a28587614c98565b6122ac9190614c98565b6122b69190614c98565b6064146122fb5760405162461bcd60e51b815260206004820152601360248201527207468652073756d206d7573742062652031303606c1b6044820152606401610fca565b601a849055601b839055601c829055601d8190556040805185815260208101859052908101839052606081018290527fbf2a0c734d68fd8490304294767942f9417a94f2834edaa62fecf9c76abb076890608001611ee8565b6005546001600160a01b0316331461237e5760405162461bcd60e51b8152600401610fca90614b9e565b60055460ff600160a01b90910416151581151514156123ee5760405162461bcd60e51b815260206004820152602660248201527f4e65772076616c7565206973207468652073616d652061732063757272656e746044820152652076616c756560d01b6064820152608401610fca565b60058054821515600160a01b0260ff60a01b199091161790556040517f1ab42d691b06b8b4e813592bf56d49d16a096d1aeb3963aec49ace70bbf2d00b90611a9690831515815260200190565b6005546001600160a01b031633146124655760405162461bcd60e51b8152600401610fca90614b9e565b603254600160b01b900460ff161561247c57600080fd5b6032805460ff60b01b1916600160b01b179055436033556034819055604051600181527f94ceecefa8cebcfa143903429574e20ce9424e1e52abaf30db6548b79956965090602001611a96565b6014546001600160a01b031633146124f35760405162461bcd60e51b8152600401610fca90614b5a565b6121263033612501306120d7565b6135d3565b6060600480546112a590614cfa565b6005546001600160a01b0316331461253f5760405162461bcd60e51b8152600401610fca90614b9e565b80516003146125a05760405162461bcd60e51b815260206004820152602760248201527f796f75206861766520746f206769766520616e206172726179207769746820336044820152662076616c75657360c81b6064820152608401610fca565b600a816000815181106125c357634e487b7160e01b600052603260045260246000fd5b602002602001015111156125d657600080fd5b806001815181106125f757634e487b7160e01b600052603260045260246000fd5b6020026020010151600a1461260b57600080fd5b60148160028151811061262e57634e487b7160e01b600052603260045260246000fd5b60200260200101511061264057600080fd5b8060008151811061266157634e487b7160e01b600052603260045260246000fd5b6020026020010151602260008154811061268b57634e487b7160e01b600052603260045260246000fd5b9060005260206000200181905550806001815181106126ba57634e487b7160e01b600052603260045260246000fd5b602002602001015160226001815481106126e457634e487b7160e01b600052603260045260246000fd5b90600052602060002001819055508060028151811061271357634e487b7160e01b600052603260045260246000fd5b6020026020010151602260028154811061273d57634e487b7160e01b600052603260045260246000fd5b60009182526020909120015550565b6014546001600160a01b031633146127765760405162461bcd60e51b8152600401610fca90614b5a565b6001600160a01b03811661279c5760405162461bcd60e51b8152600401610fca90614b0f565b6028546001600160a01b03166127b181612911565b602880546001600160a01b0319166001600160a01b0384161790556127d582611aa1565b604080516001600160a01b038084168252841660208201527f92d34bee85fbb3471c4fe1be9001a7268755ff43b8f32a9471a3f78c41c2ac7791016110f4565b6014546001600160a01b0316331461283f5760405162461bcd60e51b8152600401610fca90614b5a565b6005546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015611839573d6000803e3d6000fd5b600033816128868286612b79565b9050838110156128e65760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610fca565b6113de8286868403612f57565b6000336113368185856130f5565b602381815481106120c657600080fd5b6005546001600160a01b0316331461293b5760405162461bcd60e51b8152600401610fca90614b9e565b6001600160a01b0381166000908152602c602052604090205460ff166129a35760405162461bcd60e51b815260206004820152601c60248201527f4163636f756e74206d757374206e6f74206265206578636c75646564000000006044820152606401610fca565b6001600160a01b0381166000818152602c6020908152604091829020805460ff1916905590519182527f5411747049e49a4928cc1f7614fce69f0eeb03028d8b5e6751954194541dae119101611a96565b6014546001600160a01b03163314612a1e5760405162461bcd60e51b8152600401610fca90614b5a565b602554821115612a835760405162461bcd60e51b815260206004820152602a60248201527f416d6f756e742063616e6e6f742062652067726561746572207468616e20746f60448201526974616c4c6f747465727960b01b6064820152608401610fca565b612a8e3082846135d3565b602554612a9b9083613743565b602555604080516001600160a01b0383168152602081018490527f3a98fb46769dfe100b30c1da7304246859fd7c1b2e09bd8f3127e8cf2605265b91016110f4565b6014546001600160a01b03163314612b075760405162461bcd60e51b8152600401610fca90614b5a565b6001600160a01b038116612b705760405162461bcd60e51b815260206004820152602a60248201527f4d756c74697369673a206e6577206d756c746973696720697320746865207a65604482015269726f206164647265737360b01b6064820152608401610fca565b61183981613be9565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6005546001600160a01b03163314612bce5760405162461bcd60e51b8152600401610fca90614b9e565b6032811015612c455760405162461bcd60e51b815260206004820152603760248201527f5f6368616e6365546f57696e53656c6c546178206d757374206265206772656160448201527f746572207468616e206f7220657175616c20746f2035300000000000000000006064820152608401610fca565b60c8811115612cb45760405162461bcd60e51b815260206004820152603560248201527f5f6368616e6365546f57696e53656c6c546178206d757374206265206c6573736044820152740207468616e206f7220657175616c20746f2032303605c1b6064820152608401610fca565b600980549082905560408051828152602081018490527f7967308f951657e9cd1b4d70be1e6b6844ecdd6e5c275f8fcd283cd84ac179e991016110f4565b6005546001600160a01b03163314612d1c5760405162461bcd60e51b8152600401610fca90614b9e565b6031805460ff19168215159081179091556040519081527fbc352061858700daa9e6a46cdc7c38889a043586646c8468eefb223756fd354290602001611a96565b6005546001600160a01b03163314612d875760405162461bcd60e51b8152600401610fca90614b9e565b6001600160a01b038116612dec5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610fca565b61183981613b97565b6005546001600160a01b03163314612e1f5760405162461bcd60e51b8152600401610fca90614b9e565b6032811015612e965760405162461bcd60e51b815260206004820152603860248201527f5f6368616e6365546f57696e3053656c6c546178206d7573742062652067726560448201527f61746572207468616e206f7220657175616c20746f20353000000000000000006064820152608401610fca565b60c8811115612f065760405162461bcd60e51b815260206004820152603660248201527f5f6368616e6365546f57696e3053656c6c546178206d757374206265206c6573604482015275073207468616e206f7220657175616c20746f203230360541b6064820152608401610fca565b600b80549082905560408051828152602081018490527f3a20c80ad67871e7f099e47c8e0a5077e1b41a565c23ee01a964eaa886f77ba991016110f4565b6000612f508284614c98565b9392505050565b6001600160a01b038316612fb95760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610fca565b6001600160a01b03821661301a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610fca565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006130878484612b79565b905060001981146130ef57818110156130e25760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610fca565b6130ef8484848403612f57565b50505050565b6001600160a01b0383166000908152602c602052604090205460ff168061313457506001600160a01b0382166000908152602c602052604090205460ff165b15613144576120b18383836135d3565b600061314f306120d7565b603054603254919250821015906001600160a01b0386811691161480159061318557506032546001600160a01b03858116911614155b156132b35760285460405163f8b2cb4f60e01b81526001600160a01b038681166004830152600092169063f8b2cb4f9060240160206040518083038186803b1580156131d057600080fd5b505afa1580156131e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132089190614a01565b90506a084595161401484a0000006132338261322d613226896120d7565b8890612f44565b90612f44565b106132a65760405162461bcd60e51b815260206004820152603a60248201527f74686520726563697069656e742063616e6e6f74206f776e206d6f726520746860448201527f616e20312070657263656e74206f6620616c6c20746f6b656e730000000000006064820152608401610fca565b6132b18686866135d3565b505b8080156132ca5750603254600160a01b900460ff16155b80156132e457506032546001600160a01b03868116911614155b80156132f2575060315460ff165b15613314576000603054836133079190614ce3565b90506133128161374f565b505b6036546001600160a01b0316156134af57603654604051633af32abf60e01b81526001600160a01b03868116600483015290911690633af32abf9060240160206040518083038186803b15801561336a57600080fd5b505afa15801561337e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a291906149cd565b6133ee5760405162461bcd60e51b815260206004820152601e60248201527f55736572206973206e6f742077686974656c697374656420746f2062757900006044820152606401610fca565b60365460405163409e64c160e11b81526001600160a01b0386811660048301529091169063813cc9829060240160206040518083038186803b15801561343357600080fd5b505afa158015613447573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061346b9190614a01565b8311156134af5760405162461bcd60e51b8152602060048201526012602482015271109d5e481b1a5b5a5d08195e18d95959195960721b6044820152606401610fca565b603254600160b01b900460ff166135085760405162461bcd60e51b815260206004820152601960248201527f54726164696e67206973206e6f742079657420616374697665000000000000006044820152606401610fca565b6032546001600160a01b03868116911614156135ab576035541561359b576035546001600160a01b0385166000908152602f6020526040902054429161354d91614c98565b111561359b5760405162461bcd60e51b815260206004820152601860248201527f436f6f6c646f776e206973207374696c6c2061637469766500000000000000006044820152606401610fca565b6135a6858585613c3b565b6135cc565b6032546001600160a01b03858116911614156135cc576135cc858585613eab565b5050505050565b6001600160a01b0383166136295760405162461bcd60e51b815260206004820152601e60248201527f7472616e736665722066726f6d20746865207a65726f206164647265737300006044820152606401610fca565b6001600160a01b03821661367f5760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f2061646472657373000000006044820152606401610fca565b600061368a846120d7565b9050818110156136dc5760405162461bcd60e51b815260206004820152601f60248201527f7472616e7366657220616d6f756e7420657863656564732062616c616e6365006044820152606401610fca565b6136e68483613fd8565b6136f0838361401b565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161373591815260200190565b60405180910390a350505050565b6000612f508284614ce3565b6032805460ff60a01b1916600160a01b17905560408051600280825260608201835260009260208301908036833701905050905030816000815181106137a557634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050603160019054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b15801561381357600080fd5b505afa158015613827573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384b91906147fc565b8160018151811061386c57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03928316602091820292909201015260315461389791309161010090041684612f57565b60315460405163791ac94760e01b8152479161010090046001600160a01b03169063791ac947906138d5908690600090879030904290600401614bd3565b600060405180830381600087803b1580156138ef57600080fd5b505af1158015613903573d6000803e3d6000fd5b50505050600061391c824761374390919063ffffffff16565b9050600061394360265461322d60275461322d602554602454612f4490919063ffffffff16565b90506000613966826139606024548961403e90919063ffffffff16565b9061404a565b90506000613983836139606025548a61403e90919063ffffffff16565b905060006139a0846139606027548b61403e90919063ffffffff16565b905060006139bd856139606026548c61403e90919063ffffffff16565b905060006139da866139606024548a61403e90919063ffffffff16565b905060006139f7876139606025548b61403e90919063ffffffff16565b90506000613a14886139606027548c61403e90919063ffffffff16565b90506000613a31896139606026548d61403e90919063ffffffff16565b90508315613a75576029546040516001600160a01b039091169085156108fc029086906000818181858888f19350505050158015613a73573d6000803e3d6000fd5b505b8215613ab7576028546040516001600160a01b039091169084156108fc029085906000818181858888f19350505050158015613ab5573d6000803e3d6000fd5b505b8115613af957602b546040516001600160a01b039091169083156108fc029084906000818181858888f19350505050158015613af7573d6000803e3d6000fd5b505b8015613b3b57602a546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015613b39573d6000803e3d6000fd5b505b602454613b489089613743565b602455602554613b589088613743565b602555602754613b689087613743565b602755602654613b789086613743565b60265550506032805460ff60a01b191690555050505050505050505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b601480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f32911a2d59a9d4c952ec2065ce8e1f0ff57dc6c63e9e80e97cbe39a1c4d1254f90600090a35050565b80600080808080613c4c8689614056565b6001600160a01b038e166000908152602d60205260409020859055600554959b50929950909750955093509150600160a01b900460ff168015613c915750600c548710155b15613d56576000613ca3898989614137565b905060006025548211613cb7575080613cbc565b506025545b613cc7308b836135d3565b602554613cd49082613743565b6025556001600160a01b038a1660009081526011602052604081208054839290613cff908490614c98565b90915550508015613d53576001600d6000828254613d1d9190614c98565b9091555050600e819055600f54613d349082612f44565b600f55601080546001600160a01b0319166001600160a01b038c161790555b50505b60285460405163f8b2cb4f60e01b81526001600160a01b038a811660048301526a084595161401484a00000092613df69291169063f8b2cb4f9060240160206040518083038186803b158015613dab57600080fd5b505afa158015613dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613de39190614a01565b61322d613def8c6120d7565b8a90612f44565b1115613e6a5760405162461bcd60e51b815260206004820152603b60248201527f796f752063616e6e6f74206f776e206d6f7265207468616e203120706572636560448201527f6e74206f662074686520746f6b656e73207065722077616c6c657400000000006064820152608401610fca565b613e758989886135d3565b613e828986868686614234565b5050506006939093555050506001600160a01b03166000908152602f6020526040902042905550565b80600080808080613ebc86896142f1565b949a5091985096509094509250905082613f5a576001600160a01b0389166000908152601260205260409020805460ff19166001179055613efe8989886135d3565b6001600d6000828254613f119190614c98565b9091555050604051600181526001600160a01b038a16907f3ea6aeb2e34388609f28505d9c8e2c2ceac13b6e8ae54882da102c4bf2eaa71b9060200160405180910390a2613fcd565b613f658989886135d3565b613f728986868585614234565b6000613f7e888a6143ec565b90506000613f916064613960848c61403e565b90506025548111613fca57613fa68582613743565b600755602554613fb69082613743565b6025558015613fca57613fca308b836135d3565b50505b505050505050505050565b6001600160a01b0382166000908152602e6020526040902054613ffb9082613743565b6001600160a01b039092166000908152602e602052604090209190915550565b6001600160a01b0382166000908152602e6020526040902054613ffb9082612f44565b6000612f508284614cc4565b6000612f508284614cb0565b600080600080600080600061406b8989614426565b905060006140788a614460565b9050614089600a613960848461403e565b96506000614098886064614ce3565b90506140a960646139608d8461403e565b985060006140b78c8b613743565b90506140d360646139606016548461403e90919063ffffffff16565b97506140ef60646139606017548461403e90919063ffffffff16565b965061410b60646139606018548461403e90919063ffffffff16565b955061412760646139606019548461403e90919063ffffffff16565b9450505050509295509295509295565b600080614147600a54848761455a565b90506000614158600954858861455a565b90506000614173600a546008546145bc90919063ffffffff16565b9050600061418e6009546008546145bc90919063ffffffff16565b9050600061419c89886145c8565b9050600083861480156141c857506001600160a01b038a1660009081526013602052604090205460ff16155b1561420a5781600654116141df57506006546141e2565b50805b6001600160a01b038a166000908152601360205260409020805460ff19166001179055614227565b828514156142275781600754116142245750600754614227565b50805b9998505050505050505050565b6001600160a01b03851661428a5760405162461bcd60e51b815260206004820152601e60248201527f7461786174696f6e2066726f6d20746865207a65726f206164647265737300006044820152606401610fca565b600061429c8261322d85818989612f44565b90506142a98630836135d3565b6024546142b69086612f44565b6024556025546142c69085612f44565b6025556027546142d69084612f44565b6027556026546142e69083612f44565b602655505050505050565b60008060008060008060006143068989614675565b90506000811561431857506064614353565b60006143238b6146a5565b90506000614341600a6139606020548561403e90919063ffffffff16565b905061434e816064614ce3565b925050505b61436260646139608c8461403e565b975061436e8a89613743565b965061438a6064613960601a548a61403e90919063ffffffff16565b95506143a66064613960601b548a61403e90919063ffffffff16565b94506143c26064613960601c548a61403e90919063ffffffff16565b93506143de6064613960601d548a61403e90919063ffffffff16565b925050509295509295509295565b6021546000901561441d5760006144056064858561455a565b9050602154816144159190614d50565b91505061133c565b50600092915050565b601f5460009015614457576000614440601f54858561455a565b9050614415601e5482612f4490919063ffffffff16565b50601e5461133c565b60006144a9612710613960602360008154811061448d57634e487b7160e01b600052603260045260246000fd5b906000526020600020015460155461403e90919063ffffffff16565b8211156144e45760226000815481106144d257634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b61450f612710613960602360018154811061448d57634e487b7160e01b600052603260045260246000fd5b8211156145385760226001815481106144d257634e487b7160e01b600052603260045260246000fd5b60226002815481106144d257634e487b7160e01b600052603260045260246000fd5b60006145b48461456a8542614c98565b6040805160208101929092524490820152606085811b6bffffffffffffffffffffffff19169082015260740160408051601f198184030181529190528051602090910120906145bc565b949350505050565b6000612f508284614d50565b60285460405163f8b2cb4f60e01b81526001600160a01b03848116600483015260009283926145b4929091169063f8b2cb4f9060240160206040518083038186803b15801561461657600080fd5b505afa15801561462a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061464e9190614a01565b61466f61465a876120d7565b61466f6a084595161401484a00000088613743565b90613743565b600080614685600b54858561455a565b90506000600b546008546146999190614d50565b91909114949350505050565b60006146d2612710613960602360008154811061448d57634e487b7160e01b600052603260045260246000fd5b8211156146fb5760226002815481106144d257634e487b7160e01b600052603260045260246000fd5b614726612710613960602360018154811061448d57634e487b7160e01b600052603260045260246000fd5b82111561474f5760226001815481106144d257634e487b7160e01b600052603260045260246000fd5b60226000815481106144d257634e487b7160e01b600052603260045260246000fd5b600082601f830112614781578081fd5b8135602061479661479183614c74565b614c43565b80838252828201915082860187848660051b89010111156147b5578586fd5b855b858110156147d3578135845292840192908401906001016147b7565b5090979650505050505050565b6000602082840312156147f1578081fd5b8135612f5081614da6565b60006020828403121561480d578081fd5b8151612f5081614da6565b6000806040838503121561482a578081fd5b823561483581614da6565b9150602083013561484581614da6565b809150509250929050565b600080600060608486031215614864578081fd5b833561486f81614da6565b9250602084013561487f81614da6565b929592945050506040919091013590565b600080604083850312156148a2578182fd5b82356148ad81614da6565b946020939093013593505050565b600080604083850312156148cd578182fd5b823567ffffffffffffffff808211156148e4578384fd5b818501915085601f8301126148f7578384fd5b8135602061490761479183614c74565b8083825282820191508286018a848660051b8901011115614926578889fd5b8896505b8487101561495157803561493d81614da6565b83526001969096019591830191830161492a565b5096505086013592505080821115614967578283fd5b5061497485828601614771565b9150509250929050565b60006020828403121561498f578081fd5b813567ffffffffffffffff8111156149a5578182fd5b6145b484828501614771565b6000602082840312156149c2578081fd5b8135612f5081614dbb565b6000602082840312156149de578081fd5b8151612f5081614dbb565b6000602082840312156149fa578081fd5b5035919050565b600060208284031215614a12578081fd5b5051919050565b60008060408385031215614a2b578081fd5b82359150602083013561484581614da6565b60008060408385031215614a4f578182fd5b50508035926020909101359150565b600080600060608486031215614a72578081fd5b8351925060208401519150604084015190509250925092565b60008060008060808587031215614aa0578182fd5b5050823594602084013594506040840135936060013592509050565b6000602080835283518082850152825b81811015614ae857858101830151858201604001528201614acc565b81811115614af95783604083870101525b50601f01601f1916929092016040019392505050565b6020808252602b908201527f6e6577206c6f74746572792077616c6c65742063616e206e6f7420626520746860408201526a652030206164647265737360a81b606082015260800190565b60208082526024908201527f4d756c74697369673a2063616c6c6572206973206e6f7420746865206d756c746040820152636973696760e01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b81811015614c225784516001600160a01b031683529383019391830191600101614bfd565b50506001600160a01b03969096166060850152505050608001529392505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715614c6c57614c6c614d90565b604052919050565b600067ffffffffffffffff821115614c8e57614c8e614d90565b5060051b60200190565b60008219821115614cab57614cab614d64565b500190565b600082614cbf57614cbf614d7a565b500490565b6000816000190483118215151615614cde57614cde614d64565b500290565b600082821015614cf557614cf5614d64565b500390565b600181811c90821680614d0e57607f821691505b60208210811415614d2f57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614d4957614d49614d64565b5060010190565b600082614d5f57614d5f614d7a565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461183957600080fd5b801515811461183957600080fdfea2646970667358221220653ac46376a51b582f060bf8737a7ff28da844094d98d4f467543c650358041d64736f6c63430008040033

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

0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000065408355ffe5a612e7246b8e96ec8f3a3b3d06fc000000000000000000000000f5d1f84b5c0ab6e5024fce5d40f2acf2ad9ee99f0000000000000000000000001f58c7ae4c0cd8c91b64d0dc5b88a8ea121b3c4e000000000000000000000000f914bbdff49fd4ba1a1cbfc740e0d60a8674f438

-----Decoded View---------------
Arg [0] : _uniswapFactory (address): 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
Arg [1] : _uniswapRouter (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [2] : _lotteryWallet (address): 0x65408355ffE5a612e7246B8E96EC8F3a3B3d06FC
Arg [3] : _marketingWallet (address): 0xF5D1F84B5c0ab6E5024Fce5D40f2aCF2AD9EE99f
Arg [4] : _apadWallet (address): 0x1F58c7Ae4c0cd8C91B64d0dC5b88a8Ea121B3C4e
Arg [5] : _acapWallet (address): 0xf914BbDFf49Fd4ba1A1cBFC740E0d60a8674f438

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f
Arg [1] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [2] : 00000000000000000000000065408355ffe5a612e7246b8e96ec8f3a3b3d06fc
Arg [3] : 000000000000000000000000f5d1f84b5c0ab6e5024fce5d40f2acf2ad9ee99f
Arg [4] : 0000000000000000000000001f58c7ae4c0cd8c91b64d0dc5b88a8ea121b3c4e
Arg [5] : 000000000000000000000000f914bbdff49fd4ba1a1cbfc740e0d60a8674f438


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.