ETH Price: $3,930.53 (+0.64%)

Token

ERC-20: Hyperpool (HYPER)
 

Overview

Max Total Supply

985,192 HYPER

Holders

292

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 9 Decimals)

Balance
0.000000001 HYPER

Value
$0.00
0x97ce8d2be919ba26799d1e2be6c29bcf4f573433
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:
Token

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 25 : Hyperpool.sol
// SPDX-License-Identifier: None

pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "./interfaces/IERC721A.sol";
import "./interfaces/ITeamFinanceLocker.sol";
import "./interfaces/IToken.sol";
import "./PrizePoolV2.sol";

/// This token was incubated and launched by PROOF: https://proofplatform.io/projects. The smart contract is audited by SourceHat: https://sourcehat.com/

contract Token is IToken, ERC20, Ownable {

    struct UserInfo {
        bool isFeeExempt;
        bool isTxLimitExempt;
        uint256 lastTxBlock;
        bool isPrizePoolExcluded;
        bool isWhitelisted;
    }

    IUniswapV2Router02 public immutable uniswapV2Router;
    address public immutable pair;

    PrizePool public prizePool;

    address payable public secondaryWallet;

    address payable public immutable proofWallet;
    address payable public immutable proofStaking;

    IERC721A public proofPassNFT;

    uint256 public launchedAt;

    uint256 public maxWallet;
    uint256 public initMaxWallet;
    bool public checkMaxHoldings = true;
    bool public maxWalletChanged;

    uint256 public swapping;
    bool public swapEnabled = true;
    uint256 public swapTokensAtAmount;
    mapping (uint256 => uint256) public swapThrottle;
    uint256 public maxSwapsPerBlock = 4;
    
    FeeInfo public feeTokens;
    FeeInfo public buyFees;
    FeeInfo public sellFees;

    uint256 public restingBuyTotal;
    uint256 public restingSellTotal;
    uint256 public whitelistDuration;
    uint256 public whitelistEndTime;

    bool public isWhitelistActive;
    bool public buyTaxesSettled;
    bool public sellTaxesSettled;

    bool public proofFeeReduced;
    bool public proofFeeRemoved;
    bool public cancelled;

    uint256 public lockID;
    uint256 public immutable lpLockDuration;
    address public immutable lockerAddress;

    mapping (address => UserInfo) public userInfo;

    event SwapAndLiquify(uint256 tokensAutoLiq, uint256 ethAutoLiq);
    event SwapAndLiquifyEnabledUpdated(bool enabled);

    error InsufficientLiq();
    error NotWhitelisted();

    constructor(
        uint256 _totalSupply,
        FeeInfo memory _buyFees,
        FeeInfo memory _sellFees,
        uint256 _percentToLP,
        uint256 _lpLockDuration,
        address _secondaryWallet,
        address _proofPassNFT,
        address[] memory _whitelist,
        ProofInfo memory _addresses,
        PrizePoolInfo memory prizePoolArgs
    ) ERC20("Hyperpool", "HYPER") Ownable(msg.sender) payable {
        if (_lpLockDuration < 30 days ||  _percentToLP < 70) {
            revert InvalidConfiguration();
        }
        if (msg.value < 1 ether) {
            revert InsufficientLiq();
        }

        (_buyFees.proof, _sellFees.proof) = (2,2);
        _validateFees(_buyFees, _sellFees);
        restingBuyTotal = _buyFees.total;
        restingSellTotal = _sellFees.total;
        _buyFees.secondary = 15 - _buyFees.proof - _buyFees.main - _buyFees.liquidity;
        _buyFees.total = 15;
        _sellFees.secondary = 20 - _sellFees.proof - _sellFees.main - _sellFees.liquidity;
        _sellFees.total = 20;

        buyFees = _buyFees;
        sellFees = _sellFees;
        // set addresses
        secondaryWallet = payable(_secondaryWallet);
        prizePool = new PrizePool(prizePoolArgs.vrfCoordinator, prizePoolArgs.subscriptionId,  [50, 25, 25], prizePoolArgs.timerStart, prizePoolArgs.drawTimeHours, prizePoolArgs.entriesPerTicket);
        lockerAddress = _addresses.locker;
        proofWallet = payable(_addresses.proofWallet);
        proofStaking = payable(_addresses.proofStaking);

        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(_addresses.router);
        uniswapV2Router = _uniswapV2Router;

        pair = IUniswapV2Factory(_uniswapV2Router.factory())
            .createPair(address(this), _uniswapV2Router.WETH());

        uint256 amountToPair = _totalSupply * _percentToLP / 100;
        super._update(address(0), address(this), amountToPair); // mint to contract for liquidity

        // set basic data

        lpLockDuration = _lpLockDuration;
        swapTokensAtAmount = _totalSupply * 5 / 4000;
        initMaxWallet = 250;
        maxWallet = _totalSupply * 250 / 100000; // 100 = .1%
        
        userInfo[address(this)] = UserInfo(true, true, 0, true, true);
        userInfo[pair].isTxLimitExempt = true;
        userInfo[pair].isPrizePoolExcluded = true;
        userInfo[pair].isWhitelisted = true;
        userInfo[owner()].isPrizePoolExcluded = true;
        userInfo[_addresses.router].isPrizePoolExcluded = true;
        userInfo[address(prizePool)].isPrizePoolExcluded = true;

        proofPassNFT = IERC721A(_proofPassNFT);
        whitelistDuration = 120;
        _setWhitelisted(_whitelist);

        _updateAndSetBalance(address(0), owner(), _totalSupply - amountToPair); // mint to owner
    }

    function launch() external payable onlyOwner lockTheSwap {
        if (launchedAt != 0 || cancelled) {
            revert InvalidConfiguration();
        }

        // enable trading
        launchedAt = block.timestamp;
        whitelistEndTime = block.timestamp + whitelistDuration;
        isWhitelistActive = true;

        // add liquidity
        _approve(address(this), address(uniswapV2Router), type(uint256).max);
        addLiquidity(balanceOf(address(this)), address(this).balance - msg.value, address(this));

        // add NFT snapshot
        uint256 len = proofPassNFT.totalSupply() + 1;
        for (uint256 i = 1; i < len; ) {
            userInfo[proofPassNFT.ownerOf(i)].isWhitelisted = true;
            unchecked { ++i; }
        }

        // lock liquidity
        uint256 lpBalance = IERC20(pair).balanceOf(address(this));
        IERC20(pair).approve(lockerAddress, lpBalance);
        
        lockID = ITeamFinanceLocker(lockerAddress).lockToken{value: msg.value}(pair, msg.sender, lpBalance, block.timestamp + lpLockDuration, false, address(0));
    }

    function cancel() external onlyOwner {
        if (launchedAt != 0) {
            revert InvalidConfiguration();
        }
        cancelled = true;

        // send the tokens and eth back to the owner
        _updateAndSetBalance(address(this), owner(), balanceOf(address(this)));
        address(owner()).call{value: address(this).balance}("");
    }

    function _update(
        address from,
        address to,
        uint256 amount
    ) internal override {
        if (swapping == 2 || from == owner() || to == owner() || 
          from == address(this) || to == address(this) || amount == 0) {
            _updateAndSetBalance(from, to, amount);
            return;
        }

        if (launchedAt == 0) {
            revert TradingNotEnabled();
        }

        UserInfo storage sender = userInfo[from];
        UserInfo storage recipient = userInfo[to];

        if (isWhitelistActive) {
            if (block.timestamp < whitelistEndTime) {
                if (!sender.isWhitelisted || !recipient.isWhitelisted)
                {
                    revert NotWhitelisted();
                }
            } else {
                isWhitelistActive = false;
            }
        }

        //start at anywhere from 0.1% to 0.5%, increase by 0.1%, every 10 blocks, until it reaches 1%
        if (!maxWalletChanged) {
            uint256 secondsPassed = block.timestamp - launchedAt;
            uint256 percentage = initMaxWallet + (100 * (secondsPassed / 120));
            if (percentage > 950) {
                percentage = 1000;
                maxWalletChanged = true;
            }
            uint256 newMax = totalSupply() * percentage / 100000;
            if (newMax != maxWallet) {
                maxWallet = newMax;
            }
        }

        if (checkMaxHoldings) {
            if (!recipient.isTxLimitExempt && amount + balanceOf(to) > maxWallet) {
                revert ExceedsMaxWalletAmount();
            }
        }

        uint256 total = feeTokens.total;
        bool canSwap = total >= swapTokensAtAmount;

        if (
            canSwap &&
            swapEnabled &&
            from != pair &&
            swapThrottle[block.number] < maxSwapsPerBlock
        ) {
            ++swapThrottle[block.number];
            processFees(total, swapTokensAtAmount);
        }
        
        if (!sender.isFeeExempt && !recipient.isFeeExempt) {

            FeeInfo storage _buyFees = buyFees;
            FeeInfo storage _sellFees = sellFees;

            if (!proofFeeRemoved) {
                uint256 secondsPassed = block.timestamp - launchedAt;
                if (!proofFeeReduced && secondsPassed > 1 days) {
                    uint256 totalBuy = _buyFees.total - _buyFees.proof;
                    if (totalBuy == 0) {
                        _buyFees.total = 0;
                        _buyFees.proof = 0;
                    } else {
                        _buyFees.main = _buyFees.main + 1;
                        _buyFees.proof = 1;
                    }
                    uint256 totalSell = _sellFees.total - _sellFees.proof;
                    if (totalSell == 0) {
                        _sellFees.total = 0;
                        _sellFees.proof = 0;
                    } else {
                        _sellFees.main = _sellFees.main + 1;
                        _sellFees.proof = 1;
                    }
                    proofFeeReduced = true;
                } else if (secondsPassed > 31 days) {
                    _buyFees.main += _buyFees.proof;
                    _sellFees.main += _sellFees.proof;
                    _buyFees.proof = 0;
                    _sellFees.proof = 0;
                    proofFeeRemoved = true;
                } else {
                    if (!buyTaxesSettled) {
                        uint256 restingTotal = restingBuyTotal;
                        uint256 feeTotal = restingTotal;
                        if (secondsPassed < 1801) {
                            feeTotal = 15 - (secondsPassed / 120);
                        }
                        if (feeTotal <= restingTotal) {
                            _buyFees.total = restingTotal;
                            _buyFees.secondary = restingTotal - _buyFees.liquidity - _buyFees.main - _buyFees.proof;
                            buyTaxesSettled = true;
                        } else if (feeTotal != _buyFees.total) {
                            _buyFees.total = feeTotal;
                            _buyFees.secondary = feeTotal - _buyFees.liquidity - _buyFees.main - _buyFees.proof;
                        }
                    }
                    if (!sellTaxesSettled) {
                        uint256 restingTotal = restingSellTotal;
                        uint256 feeTotal = restingTotal;
                        if (secondsPassed < 2401) {
                            feeTotal = 20 - (secondsPassed / 120);
                        }
                        if (feeTotal <= restingTotal) {
                            _sellFees.total = restingTotal;
                            _sellFees.secondary = restingTotal - _sellFees.liquidity - _sellFees.main - _sellFees.proof;
                            sellTaxesSettled = true;
                        } else if (feeTotal != _sellFees.total) {
                            _sellFees.total = feeTotal;
                            _sellFees.secondary = feeTotal - _sellFees.liquidity - _sellFees.main - _sellFees.proof;
                        }
                    }
                }
            }

            uint256 fees;
            if (to == pair) { //sell
                fees = _calculateFees(_sellFees, amount);
            } else if (from == pair) { //buy
                fees = _calculateFees(_buyFees, amount);
            }
            if (fees > 0) {
                amount -= fees;
                super._update(from, address(this), fees);
            }
        }

        super._update(from, to, amount);

        if (!sender.isPrizePoolExcluded) {
            try prizePool.setBalance(from, balanceOf(from)) {} catch {}
        }

        if (!recipient.isPrizePoolExcluded) {
            try prizePool.setBalance(to, balanceOf(to)) {} catch {}
        }

    }

    function _calculateFees(FeeInfo memory feeRate, uint256 amount) internal returns (uint256 fees) {
        if (feeRate.total != 0) {
            fees = amount * feeRate.total / 100;
            
            FeeInfo storage _feeTokens = feeTokens;
            _feeTokens.main += fees * feeRate.main / feeRate.total;
            _feeTokens.secondary += fees * feeRate.secondary / feeRate.total;
            _feeTokens.liquidity += fees * feeRate.liquidity / feeRate.total;
            _feeTokens.proof += fees * feeRate.proof / feeRate.total;
            _feeTokens.total += fees;
        }
    }

    function processFees(uint256 total, uint256 amountToSwap) internal lockTheSwap {
        FeeInfo storage _feeTokens = feeTokens;

        FeeInfo memory swapTokens;
        swapTokens.main = amountToSwap * _feeTokens.main / total;
        swapTokens.secondary = amountToSwap * _feeTokens.secondary / total;
        swapTokens.liquidity = amountToSwap * _feeTokens.liquidity / total;
        swapTokens.proof = amountToSwap * _feeTokens.proof / total;

        uint256 amountToPair = swapTokens.liquidity / 2;

        swapTokens.total = amountToSwap - amountToPair;

        uint256 ethBalance = swapTokensForETH(swapTokens.total);

        FeeInfo memory ethSplit;

        ethSplit.main = ethBalance * swapTokens.main / swapTokens.total;
        if (ethSplit.main > 0) {
            address(prizePool).call{value: ethSplit.main}("");
        }

        ethSplit.secondary = ethBalance * swapTokens.secondary / swapTokens.total;
        if (ethSplit.secondary > 0) {
            address(secondaryWallet).call{value: ethSplit.secondary}("");
        }
        
        ethSplit.proof = ethBalance * swapTokens.proof / swapTokens.total;
        if (ethSplit.proof > 0) {
            uint256 revenueSplit = ethSplit.proof / 2;
            address(proofStaking).call{value: revenueSplit}("");
            address(proofWallet).call{value: ethSplit.proof - revenueSplit}("");
        }

        uint256 amountPaired;
        ethSplit.liquidity = address(this).balance;
        if (amountToPair > 0 && ethSplit.liquidity > 0) {
            amountPaired = addLiquidity(amountToPair, ethSplit.liquidity, address(0xdead));
            emit SwapAndLiquify(amountToPair, ethSplit.liquidity);
        }

        uint256 liquidityAdjustment = swapTokens.liquidity - (amountToPair - amountPaired);

        _feeTokens.main -= swapTokens.main;
        _feeTokens.secondary -= swapTokens.secondary;
        _feeTokens.liquidity -= liquidityAdjustment;
        _feeTokens.proof -= swapTokens.proof;
        _feeTokens.total -= swapTokens.main + swapTokens.secondary + swapTokens.proof + liquidityAdjustment;
    }

    function swapTokensForETH(uint256 tokenAmount) internal returns (uint256 ethBalance) {
        uint256 ethBalBefore = address(this).balance;

        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();

        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of ETH
            path,
            address(this),
            block.timestamp
        );

        ethBalance = address(this).balance - ethBalBefore;
    }

    function addLiquidity(uint256 tokenAmount, uint256 ethAmount, address recipient) private returns (uint256) {
        (uint256 amountA,,) = uniswapV2Router.addLiquidityETH{value: ethAmount}(
            address(this),
            tokenAmount,
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            recipient,
            block.timestamp
        );
        return amountA;
    }

    function burn(uint256 amount) external {
        super._burn(msg.sender, amount);
        if (!userInfo[msg.sender].isPrizePoolExcluded) {
            try prizePool.burn(msg.sender, amount) {} catch {}
            try prizePool.setBalance(msg.sender, balanceOf(msg.sender)) {} catch {}
        }
    }

    function changeFees(
        uint256 liquidityBuy,
        uint256 mainBuy,
        uint256 secondaryBuy,
        uint256 liquiditySell,
        uint256 mainSell,
        uint256 secondarySell
    ) external onlyOwner {
        if (!buyTaxesSettled || !sellTaxesSettled) {
            revert InvalidConfiguration();
        }
        FeeInfo memory _buyFees;
        _buyFees.liquidity = liquidityBuy;
        _buyFees.main = mainBuy;
        _buyFees.secondary = secondaryBuy;

        FeeInfo memory _sellFees;
        _sellFees.liquidity = liquiditySell;
        _sellFees.main = mainSell;
        _sellFees.secondary = secondarySell;

        (_buyFees.proof, _sellFees.proof) = launchedAt != 0 ? _calculateProofFee() : (2,2);
        _validateFees(_buyFees, _sellFees);
        buyFees = _buyFees;
        sellFees = _sellFees;
    }

    function _calculateProofFee() internal returns (uint256, uint256) {
        uint256 secondsPassed = block.timestamp - launchedAt;
        if (secondsPassed > 31 days) {
            proofFeeRemoved = true;
            return (0,0);
        } else if (secondsPassed > 1 days) {
            proofFeeReduced = true;
            return (1,1);
        } else {
            return (2,2);
        }
    }

    function _validateFees(FeeInfo memory _buyFees, FeeInfo memory _sellFees) internal pure {
        _buyFees.total = _buyFees.liquidity + _buyFees.main + _buyFees.secondary;
        if (_buyFees.total == 0) {
            _buyFees.proof = 0;
        } else {
             _buyFees.total += _buyFees.proof;
        }

        _sellFees.total = _sellFees.liquidity + _sellFees.main + _sellFees.secondary;
        if (_sellFees.total == 0) {
            _sellFees.proof = 0;
        } else {
            _sellFees.total += _sellFees.proof;
        }

        if (_buyFees.total > 7 || _sellFees.total > 7) {
            revert InvalidConfiguration();
        }

    }

    function setCheckMaxHoldingsEnabled(bool _enabled) external onlyOwner{
        checkMaxHoldings = _enabled;
    }

    function setFeeExempt(address account, bool value) public onlyOwner {
        userInfo[account].isFeeExempt = value;
    }

    function setFeeExempt(address[] memory accounts) public onlyOwner {
        uint256 len = accounts.length;
        for (uint256 i; i < len; i++) {
            userInfo[accounts[i]].isFeeExempt = true;
        }
    }

    function setSecondaryWallet(address newWallet) external onlyOwner {
        secondaryWallet = payable(newWallet);
    }

    function updatePrizePool(address newAddress) public onlyOwner {
        require(newAddress != address(prizePool));

        PrizePool newPrizePool = PrizePool(payable(newAddress));

        require(newPrizePool.owner() == address(this));

        prizePool = newPrizePool;
    }

    function setSwapAndLiquifyEnabled(bool _enabled) external onlyOwner {
        swapEnabled = _enabled;
        emit SwapAndLiquifyEnabledUpdated(_enabled);
    }

    function setSwapAtAmount(uint256 amount) external onlyOwner {
        swapTokensAtAmount = amount;
    }

    function setMaxSwapsPerBlock(uint256 _maxSwaps) external onlyOwner {
        maxSwapsPerBlock = _maxSwaps;
    }

    function setAllocationPercentages(uint256 _dailyAllocation, uint256 _weeklyAllocation, uint256 _monthlyAllocation) external onlyOwner {
        prizePool.setAllocationPercentages(_dailyAllocation, _weeklyAllocation, _monthlyAllocation);
    }

    function updatePoolIntervals(
        uint256[] calldata newIntervals
    ) external onlyOwner {
        prizePool.updatePoolIntervals(newIntervals);
    }

    function updateEntriesPerTicket(uint256 _entriesPerTicket) external onlyOwner {
        prizePool.updateEntriesPerTicket(_entriesPerTicket);
    }

    function updateBurnMultiplier(uint256 newMultiplier) external onlyOwner {
        prizePool.updateBurnMultiplier(newMultiplier);
    }

    function updateGasLimit(uint32 newLimit) external onlyOwner {
        prizePool.updateGasLimit(newLimit);
    }

    function setPrizeExcluded(address account, bool value) public onlyOwner {
        userInfo[account].isPrizePoolExcluded = value;
        try prizePool.setExcluded(account, value, balanceOf(account)) {} catch {}
    }

    function setPrizeExcludedMany(address[] memory accounts) public onlyOwner {
        uint256 len = accounts.length;
        for (uint256 i; i < len; i++) {
            try prizePool.setExcluded(accounts[i], true, balanceOf(accounts[i])) {} catch {}
        }
    }

    function setWhitelisted(address[] memory accounts) external onlyOwner {
        if (launchedAt != 0) {
            revert InvalidConfiguration();
        }
        _setWhitelisted(accounts);
    }

    function _setWhitelisted(address[] memory accounts) internal {
        uint256 len = accounts.length;
        for (uint256 i; i < len; i++) {
            userInfo[accounts[i]].isWhitelisted = true;
        }
    }

    function pausePrizeDraws(bool value) external onlyOwner {
        prizePool.pausePrizeDraws(value);
    }

    function updateDrawTime(uint256 timeInHours) external onlyOwner {
        prizePool.updateDrawTime(timeInHours);
    }

    function updateCoordinator(address _coordinator) external onlyOwner {
        prizePool.updateCoordinator(_coordinator);
    }

    function updateKeyHash(bytes32 _keyhash) external onlyOwner {
        prizePool.updateKeyHash(_keyhash);
    }

    function updateSubscriptionID(uint256 _subID) external onlyOwner {
        prizePool.updateSubscriptionID(_subID);
    }

    function withdrawStuckTokens() external onlyOwner {
        _updateAndSetBalance(address(this), _msgSender(), balanceOf(address(this)) - feeTokens.total);
    }

    function _updateAndSetBalance(address from, address to, uint256 amount) internal {
        super._update(from, to, amount);
        if (!userInfo[from].isPrizePoolExcluded) {
            try prizePool.setBalance(from, balanceOf(from)) {} catch {}
        }

        if (!userInfo[to].isPrizePoolExcluded) {
            try prizePool.setBalance(to, balanceOf(to)) {} catch {}
        }
    }

    function getCirculatingSupply() external view returns (uint256) {
        return totalSupply() - balanceOf(address(0xdead));
    }

    modifier lockTheSwap() {
        swapping = 2;
        _;
        swapping = 1;
    }

    function decimals() public view virtual override returns (uint8) {
        return 9;
    }

    function version() public pure returns (uint8) {
        return 1;
    }

    receive() external payable {}
 
}

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

import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol";
import {IVRFSubscriptionV2Plus} from "./IVRFSubscriptionV2Plus.sol";

// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades
// This interface is supported by subsequent versions of VRFCoordinatorV2Plus
interface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus {
  /**
   * @notice Request a set of random words.
   * @param req - a struct containing following fields for randomness request:
   * 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.
   * subId  - The ID of the VRF subscription. Must be funded
   * with the minimum subscription balance required for the selected keyHash.
   * requestConfirmations - 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].
   * 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]
   * 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.
   * extraArgs - abi-encoded extra args
   * @return requestId - A unique identifier of the request. Can be used to match
   * a request to a response in fulfillRandomWords.
   */
  function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId);
}

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

/// @notice The IVRFSubscriptionV2Plus interface defines the subscription
/// @notice related methods implemented by the V2Plus coordinator.
interface IVRFSubscriptionV2Plus {
  /**
   * @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(uint256 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(uint256 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(uint256 subId, address to) external;

  /**
   * @notice Accept 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(uint256 subId) external;

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

  /**
   * @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 with LINK, use transferAndCall. For example
   * @dev  LINKTOKEN.transferAndCall(
   * @dev    address(COORDINATOR),
   * @dev    amount,
   * @dev    abi.encode(subId));
   * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure
   * @dev  to send Native with the call, for example:
   * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId);
   */
  function createSubscription() external returns (uint256 subId);

  /**
   * @notice Get a VRF subscription.
   * @param subId - ID of the subscription
   * @return balance - LINK balance of the subscription in juels.
   * @return nativeBalance - native balance of the subscription in wei.
   * @return reqCount - Requests count of subscription.
   * @return owner - owner of the subscription.
   * @return consumers - list of consumer address which are able to use this subscription.
   */
  function getSubscription(
    uint256 subId
  )
    external
    view
    returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers);

  /*
   * @notice Check to see if there exists a request commitment consumers
   * for all consumers and keyhashes for a given sub.
   * @param subId - ID of the subscription
   * @return true if there exists at least one unfulfilled request for the subscription, false
   * otherwise.
   */
  function pendingRequestExists(uint256 subId) external view returns (bool);

  /**
   * @notice Paginate through all active VRF subscriptions.
   * @param startIndex index of the subscription to start from
   * @param maxCount maximum number of subscriptions to return, 0 to return all
   * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one
   * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state
   */
  function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory);

  /**
   * @notice Fund a subscription with native.
   * @param subId - ID of the subscription
   * @notice This method expects msg.value to be greater than or equal to 0.
   */
  function fundSubscriptionWithNative(uint256 subId) external payable;
}

File 4 of 25 : VRFV2PlusClient.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

// End consumer library.
library VRFV2PlusClient {
  // extraArgs will evolve to support new features
  bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256("VRF ExtraArgsV1"));
  struct ExtraArgsV1 {
    bool nativePayment;
  }

  struct RandomWordsRequest {
    bytes32 keyHash;
    uint256 subId;
    uint16 requestConfirmations;
    uint32 callbackGasLimit;
    uint32 numWords;
    bytes extraArgs;
  }

  function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
    return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);
  }
}

File 5 of 25 : VRFConsumerBaseV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/** ****************************************************************************
 * @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);
  // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i
  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
   */
  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
  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 6 of 25 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

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

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

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

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

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

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 8 of 25 : IERC1363.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.20;

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

File 10 of 25 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

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

File 11 of 25 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

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

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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

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

        emit Transfer(from, to, value);
    }

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

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

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

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

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

File 12 of 25 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

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

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

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

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

File 13 of 25 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

File 14 of 25 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

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

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

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

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

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

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

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

File 15 of 25 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

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

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

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

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

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

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

pragma solidity ^0.8.20;

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

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

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

File 17 of 25 : Errors.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)

pragma solidity ^0.8.20;

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

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

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

    /**
     * @dev A necessary precompile is missing.
     */
    error MissingPrecompile(address);
}

File 18 of 25 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

File 19 of 25 : 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 20 of 25 : 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 21 of 25 : 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 22 of 25 : IERC721A.sol
// SPDX-License-Identifier: None

pragma solidity ^0.8.24;

interface IERC721A {
    function totalSupply() external returns (uint256);
    function ownerOf(uint256) external returns (address);
}

File 23 of 25 : ITeamFinanceLocker.sol
// SPDX-License-Identifier: None

pragma solidity ^0.8.24;

interface ITeamFinanceLocker {
    function lockToken(
        address _tokenAddress,
        address _withdrawalAddress,
        uint256 _amount,
        uint256 _unlockTime,
        bool _mintNFT, 
        address referrer
    ) external payable returns (uint256 _id);
}

File 24 of 25 : IToken.sol
// SPDX-License-Identifier: None

pragma solidity ^0.8.24;

interface IToken {
    struct FeeInfo {
        uint256 main;
        uint256 secondary;
        uint256 liquidity;
        uint256 proof;
        uint256 total;
    }

    struct ProofInfo {
        address locker;
        address router;
        address proofWallet;
        address proofStaking;
    }

    struct PrizePoolInfo {
        address vrfCoordinator;
        uint256 subscriptionId;
        uint256 timerStart;
        uint256 drawTimeHours;
        uint256 entriesPerTicket;
    }

    error ExceedsMaxTxAmount();
    error ExceedsMaxWalletAmount();
    error InvalidConfiguration();
    error TradingNotEnabled();
    error TransferDelayEnabled(uint256 currentBlock, uint256 delayedUntil);
}

File 25 of 25 : PrizePoolV2.sol
// SPDX-License-Identifier: None

pragma solidity ^0.8.24;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
import {IVRFCoordinatorV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol";
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";

error InvalidConfiguration();
error StakeLocked();
error DrawNotReady();
error RegistrationError();
error LotteryPaused();
error InsufficientStakeBalance();

event WinnerSelected(uint256 poolDraw, address winner, uint256 amount, uint256 winningNumber);

contract PrizePool is VRFConsumerBaseV2, Ownable {
    using SafeERC20 for IERC20;

    struct UserInfo {
        uint256 staked;
        uint256 burnBonus;
        mapping(uint256 => uint256[]) indexes;
        uint256 lastStakedTime;
    }

    struct Pool {
        uint256 lastDrawTime;
        uint256 interval;
        uint256 allocPercent;
        uint256 currentRewards;
    }

    mapping(address => UserInfo) public userInfo;
    mapping(uint256 => Pool) public prizePools;

    IERC20 public hype;
    uint256 public DRAW_TIME_OF_DAY = 0; //used to determine what time we want the next draw to be available
    //Seconds from midnight, for example if we want 3pm DRAW_TIME_OF_DAY should be 15 hours

    uint256[] private currentPoolDraws;
    uint256 public burnMultiplier = 4;
    uint256 remainder; //for leftover wei after distributions to pools

    uint256 subscriptionId;
    IVRFCoordinatorV2Plus coordinator;
    address vrfCoordinator;
    bytes32 keyHash = 0x8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef; //mainnet
    uint32 callbackGasLimit = 15000000;
    uint16 requestConfirmations = 3;
    bool paused = false;

    uint256 public entriesPerTicket;
    uint256 public totalTickets;
    mapping(uint256 => uint256) public totalToUserIndexes;
    mapping(uint256 => address[]) ticketList;
    uint256 currListID;

    constructor(
        address _vrfCoordinator,
        uint256 _subscriptionId,
        uint8[3] memory poolAllocations,
        uint256 drawTimerStart,
        uint256 drawTimeHours,
        uint256 _entriesPerTicket
    ) VRFConsumerBaseV2(_vrfCoordinator) Ownable(msg.sender) {
        hype = IERC20(msg.sender);
        if (poolAllocations[0] + poolAllocations[1] + poolAllocations[2] != 100) {
            revert InvalidConfiguration();
        }
        prizePools[0] = Pool(
            drawTimerStart,
            1 days,
            poolAllocations[0],
            0
        );
        prizePools[1] = Pool(
            drawTimerStart,
            7 days,
            poolAllocations[1],
            0
        );
        prizePools[2] = Pool(
            drawTimerStart,
            30 days,
            poolAllocations[2],
            0
        );

        entriesPerTicket = _entriesPerTicket;
        coordinator = IVRFCoordinatorV2Plus(_vrfCoordinator);
        subscriptionId = _subscriptionId;
        DRAW_TIME_OF_DAY = drawTimeHours * 3600;
    }

    function setBalance(address account, uint256 newBalance) external onlyOwner {
    	_setBalance(account, newBalance);
    }

    function _setBalance(address account, uint256 newBalance) internal {
    	UserInfo storage user = userInfo[account];
        uint256 id = currListID;
        uint256 numTickets = (newBalance + (user.staked * 2) + (user.burnBonus)) / entriesPerTicket;
        if(numTickets > user.indexes[id].length) {
    		addUser(account, numTickets);
    	} else if (numTickets < user.indexes[id].length) {
    		removeUser(account, numTickets);
    	}
    }

    function addUser(address account, uint256 numTickets) internal {
        UserInfo storage user = userInfo[account];
        uint256 id = currListID;
        uint256 toAdd = numTickets - user.indexes[id].length;
        address[] storage list = ticketList[id];
        uint256 startingIndex = list.length;
        for (uint256 i; i < toAdd; i++) {
            user.indexes[id].push(startingIndex + i);
            list.push(account);
            totalToUserIndexes[startingIndex + i] = user.indexes[id].length - 1;
        }
        totalTickets += toAdd;
    }


    function removeUser(address account, uint256 numTickets) internal {
        UserInfo storage user = userInfo[account];
        uint256 id = currListID;
        uint256 toRemove = user.indexes[id].length - numTickets;
        address[] storage _ticketList = ticketList[id];
        for (uint256 i; i < toRemove; i++) {
            uint256 lastTicket = _ticketList.length - 1;
            uint256[] memory userIndexes = user.indexes[id];
            UserInfo storage movedUser = userInfo[_ticketList[lastTicket]];
            _ticketList[userIndexes[userIndexes.length - 1]] = _ticketList[lastTicket]; //replace last user entry in list with last overall entry
            movedUser.indexes[id][totalToUserIndexes[lastTicket]] = userIndexes[userIndexes.length - 1]; //update moved users index array
            totalToUserIndexes[userIndexes[userIndexes.length - 1]] = totalToUserIndexes[lastTicket]; //update index tracker
            user.indexes[id].pop();
            _ticketList.pop();
        }
        totalTickets -= toRemove;
    }


    receive() external payable {
        uint256 toDistribute = msg.value + remainder;

        Pool storage pool0 = prizePools[0];
        Pool storage pool1 = prizePools[1];
        Pool storage pool2 = prizePools[2];

        uint256 pool0Reward = (toDistribute * pool0.allocPercent) / 100;
        uint256 pool1Reward = (toDistribute * pool1.allocPercent) / 100;
        uint256 pool2Reward = (toDistribute * pool2.allocPercent) / 100;

        pool0.currentRewards += pool0Reward;
        pool1.currentRewards += pool1Reward;
        pool2.currentRewards += pool2Reward;

        remainder = toDistribute - pool0Reward - pool1Reward - pool2Reward;
    }

    function stake(uint256 amount) external {
        userInfo[msg.sender].staked += amount;
        userInfo[msg.sender].lastStakedTime = block.timestamp;
        hype.safeTransferFrom(address(msg.sender), address(this), amount);
    }

    function unstake(uint256 amount) external {
        if (block.timestamp < userInfo[msg.sender].lastStakedTime + 7 days) {
            revert StakeLocked();
        }
        if (userInfo[msg.sender].staked < amount) {
            revert InsufficientStakeBalance();
        }
        userInfo[msg.sender].staked -= amount;
        hype.safeTransfer(address(msg.sender), amount);
    }

    function burn(address account, uint256 amount) external onlyOwner {
        userInfo[account].burnBonus += amount * burnMultiplier;
    }

    function draw() external {
        if (paused) {
            revert LotteryPaused();
        }
        delete currentPoolDraws;
        uint256 available;
        uint256 currTime = block.timestamp;
        uint256 timeOfDay = DRAW_TIME_OF_DAY;
        for (uint256 i = 0; i < 3; i++) {
            Pool storage pool = prizePools[i];
            if (pool.lastDrawTime + pool.interval <= block.timestamp && pool.currentRewards != 0) {
                prizePools[i].lastDrawTime = currTime - (currTime % 86400) + timeOfDay;
                currentPoolDraws.push(i);
                available++;
            }
        }
        if (available == 0 || totalTickets == 0) {
            revert DrawNotReady();
        }
        requestRandomWords(callbackGasLimit, requestConfirmations, 1);
    }

    function selectWinner(uint256 randomness) internal {
        uint256[] memory poolIDs = currentPoolDraws;
        uint256 numberOfDraws = poolIDs.length;
        uint256 randNonce;
        bool success;
        for (uint256 i; i < numberOfDraws; i++) {
            uint256 winningNumber = (uint256(keccak256(abi.encodePacked(randomness, randNonce))) % totalTickets);
            randNonce++;
            uint256 poolReward = prizePools[poolIDs[i]].currentRewards;
            (success, ) = ticketList[currListID][winningNumber].call{value: poolReward}("");
            if (success) prizePools[poolIDs[i]].currentRewards = 0;
            emit WinnerSelected(poolIDs[i], ticketList[currListID][winningNumber], poolReward, winningNumber);
        }
    }

    function requestRandomWords(
        uint32 _callbackGasLimit,
        uint16 _requestConfirmations,
        uint32 _numWords
    ) internal {
        bytes memory args = VRFV2PlusClient._argsToBytes(
            VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
        );

        VRFV2PlusClient.RandomWordsRequest memory request = VRFV2PlusClient
            .RandomWordsRequest({
                keyHash: keyHash,
                subId: subscriptionId,
                requestConfirmations: _requestConfirmations,
                callbackGasLimit: _callbackGasLimit,
                numWords: _numWords,
                extraArgs: args
            });

        coordinator.requestRandomWords(request);
    }

    function fulfillRandomWords(
        uint256 _requestId,
        uint256[] memory randomWords
    ) internal override {
        selectWinner(randomWords[0]);
    }

    function register() external {
        _setBalance(msg.sender, hype.balanceOf(msg.sender));
    }

    /****************** OWNER CONTROL ******************/

    function setAllocationPercentages(
        uint256 pool1Allocation,
        uint256 pool2Allocation,
        uint256 pool3Allocation
    ) external onlyOwner {
        _setAllocationPercentages(
            pool1Allocation,
            pool2Allocation,
            pool3Allocation
        );
    }

    function _setAllocationPercentages(
        uint256 _pool1Allocation,
        uint256 _pool2Allocation,
        uint256 _pool3Allocation
    ) internal {
        if (_pool1Allocation + _pool2Allocation + _pool3Allocation != 100) {
            revert InvalidConfiguration();
        }

        prizePools[0].allocPercent = _pool1Allocation;
        prizePools[1].allocPercent = _pool2Allocation;
        prizePools[2].allocPercent = _pool3Allocation;
    }

    function updatePoolIntervals(
        uint256[] calldata newIntervals
    ) external onlyOwner {
        if (newIntervals.length != 3 ||
            newIntervals[0] % 86400 != 0 ||
            newIntervals[1] % 86400 != 0 ||
            newIntervals[2] % 86400 != 0
        ) { revert InvalidConfiguration(); }
        prizePools[0].interval = newIntervals[0];
        prizePools[1].interval = newIntervals[1];
        prizePools[2].interval = newIntervals[2];
    }

    function updateEntriesPerTicket(uint256 _entriesPerTicket) external onlyOwner {
        if (_entriesPerTicket < 10**9) {
            revert InvalidConfiguration();
        }
        entriesPerTicket = _entriesPerTicket;
        currListID++;
        totalTickets = 0;
    }

    function updateBurnMultiplier(uint256 newMultiplier) external onlyOwner {
        burnMultiplier = newMultiplier;
    }

    function updateGasLimit(uint32 newLimit) external onlyOwner {
        callbackGasLimit = newLimit;
    }

    function setExcluded(address account, bool value, uint256 balance) external onlyOwner {
        if (value) {
            removeUser(account, 0);
        } else {
            _setBalance(account, balance);
        }
    }
    
    function pausePrizeDraws(bool value) external onlyOwner {
        paused = value;
    }

    function updateDrawTime(uint256 timeInHours) external onlyOwner {
        DRAW_TIME_OF_DAY = timeInHours * 3600;
    }

    function updateCoordinator(address _coordinator) external onlyOwner {
        coordinator = IVRFCoordinatorV2Plus(_coordinator);
    }

    function updateKeyHash(bytes32 _keyHash) external onlyOwner {
        keyHash = _keyHash;
    }

    function updateSubscriptionID(uint256 _subId) external onlyOwner {
        subscriptionId = _subId;
    }

    function getUserPoints(address user) external view returns (uint256) {
        UserInfo storage _user = userInfo[user];
        return (hype.balanceOf(user) + (_user.staked * 2) + (_user.burnBonus));
    }

    function getUserTickets(address user) external view returns (uint256) {
        return userInfo[user].indexes[currListID].length;
    }

}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"components":[{"internalType":"uint256","name":"main","type":"uint256"},{"internalType":"uint256","name":"secondary","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"proof","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"internalType":"struct IToken.FeeInfo","name":"_buyFees","type":"tuple"},{"components":[{"internalType":"uint256","name":"main","type":"uint256"},{"internalType":"uint256","name":"secondary","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"proof","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"internalType":"struct IToken.FeeInfo","name":"_sellFees","type":"tuple"},{"internalType":"uint256","name":"_percentToLP","type":"uint256"},{"internalType":"uint256","name":"_lpLockDuration","type":"uint256"},{"internalType":"address","name":"_secondaryWallet","type":"address"},{"internalType":"address","name":"_proofPassNFT","type":"address"},{"internalType":"address[]","name":"_whitelist","type":"address[]"},{"components":[{"internalType":"address","name":"locker","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"proofWallet","type":"address"},{"internalType":"address","name":"proofStaking","type":"address"}],"internalType":"struct IToken.ProofInfo","name":"_addresses","type":"tuple"},{"components":[{"internalType":"address","name":"vrfCoordinator","type":"address"},{"internalType":"uint256","name":"subscriptionId","type":"uint256"},{"internalType":"uint256","name":"timerStart","type":"uint256"},{"internalType":"uint256","name":"drawTimeHours","type":"uint256"},{"internalType":"uint256","name":"entriesPerTicket","type":"uint256"}],"internalType":"struct IToken.PrizePoolInfo","name":"prizePoolArgs","type":"tuple"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"ExceedsMaxTxAmount","type":"error"},{"inputs":[],"name":"ExceedsMaxWalletAmount","type":"error"},{"inputs":[],"name":"InsufficientLiq","type":"error"},{"inputs":[],"name":"InvalidConfiguration","type":"error"},{"inputs":[],"name":"NotWhitelisted","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"TradingNotEnabled","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentBlock","type":"uint256"},{"internalType":"uint256","name":"delayedUntil","type":"uint256"}],"name":"TransferDelayEnabled","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"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":"uint256","name":"tokensAutoLiq","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethAutoLiq","type":"uint256"}],"name":"SwapAndLiquify","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"SwapAndLiquifyEnabledUpdated","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"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyFees","outputs":[{"internalType":"uint256","name":"main","type":"uint256"},{"internalType":"uint256","name":"secondary","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"proof","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyTaxesSettled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidityBuy","type":"uint256"},{"internalType":"uint256","name":"mainBuy","type":"uint256"},{"internalType":"uint256","name":"secondaryBuy","type":"uint256"},{"internalType":"uint256","name":"liquiditySell","type":"uint256"},{"internalType":"uint256","name":"mainSell","type":"uint256"},{"internalType":"uint256","name":"secondarySell","type":"uint256"}],"name":"changeFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkMaxHoldings","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTokens","outputs":[{"internalType":"uint256","name":"main","type":"uint256"},{"internalType":"uint256","name":"secondary","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"proof","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCirculatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initMaxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWhitelistActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"launchedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpLockDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSwapsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWalletChanged","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"pausePrizeDraws","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"prizePool","outputs":[{"internalType":"contract PrizePool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofFeeReduced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofFeeRemoved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofPassNFT","outputs":[{"internalType":"contract IERC721A","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofStaking","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restingBuyTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"restingSellTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondaryWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellFees","outputs":[{"internalType":"uint256","name":"main","type":"uint256"},{"internalType":"uint256","name":"secondary","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"proof","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellTaxesSettled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_dailyAllocation","type":"uint256"},{"internalType":"uint256","name":"_weeklyAllocation","type":"uint256"},{"internalType":"uint256","name":"_monthlyAllocation","type":"uint256"}],"name":"setAllocationPercentages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setCheckMaxHoldingsEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setFeeExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"setFeeExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxSwaps","type":"uint256"}],"name":"setMaxSwapsPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setPrizeExcluded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"setPrizeExcludedMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWallet","type":"address"}],"name":"setSecondaryWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setSwapAndLiquifyEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setSwapAtAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"setWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"swapThrottle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapTokensAtAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapping","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMultiplier","type":"uint256"}],"name":"updateBurnMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_coordinator","type":"address"}],"name":"updateCoordinator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeInHours","type":"uint256"}],"name":"updateDrawTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_entriesPerTicket","type":"uint256"}],"name":"updateEntriesPerTicket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newLimit","type":"uint32"}],"name":"updateGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_keyhash","type":"bytes32"}],"name":"updateKeyHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"newIntervals","type":"uint256[]"}],"name":"updatePoolIntervals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"updatePrizePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_subID","type":"uint256"}],"name":"updateSubscriptionID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"bool","name":"isFeeExempt","type":"bool"},{"internalType":"bool","name":"isTxLimitExempt","type":"bool"},{"internalType":"uint256","name":"lastTxBlock","type":"uint256"},{"internalType":"bool","name":"isPrizePoolExcluded","type":"bool"},{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"whitelistDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawStuckTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101406040819052600c8054600160ff199182168117909255600e80549091169091179055600460115562006f2938819003908190833981016040819052620000489162000cda565b3360405180604001604052806009815260200168121e5c195c9c1bdbdb60ba1b81525060405180604001604052806005815260200164242ca822a960d91b81525081600390816200009a919062000ec7565b506004620000a9828262000ec7565b5050506001600160a01b038116620000dc57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620000e781620006a2565b5062278d00861080620000fa5750604687105b15620001195760405163c52a9bd360e01b815260040160405180910390fd5b670de0b6b3a76400003410156200014357604051632b9111c360e21b815260040160405180910390fd5b600260608981018290528a01526200015c8989620006f4565b6080808a01516021558801516022556040890151895160608b01516200018490600f62000fa9565b62000190919062000fa9565b6200019c919062000fa9565b60208a0152600f60808a01526040880151885160608a0151620001c190601462000fa9565b620001cd919062000fa9565b620001d9919062000fa9565b8860200181815250506014886080018181525050886017600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505087601c600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505084600760006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806000015181602001516040518060600160405280603260ff168152602001601960ff168152602001601960ff16815250836040015184606001518560800151604051620002d29062000b05565b620002e39695949392919062000fc5565b604051809103906000f08015801562000300573d6000803e3d6000fd5b50600680546001600160a01b0319166001600160a01b039283161790558251811661012052604080840151821660c0526060840151821660e0526020808501519283166080819052825163c45a015560e01b81529251909263c45a01559260048083019391928290030181865afa15801562000380573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a691906200102a565b6001600160a01b031663c9c6539630836001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041a91906200102a565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af115801562000468573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200048e91906200102a565b6001600160a01b031660a05260006064620004aa8a8e6200104f565b620004b6919062001069565b9050620004c660003083620007e7565b610100889052610fa0620004dc8d60056200104f565b620004e8919062001069565b600f5560fa600b819055620186a09062000504908e906200104f565b62000510919062001069565b600a556040805160a080820183526001808352602080840182815260008587018181526060870185815260808801868152308452602795869052898420985189549551151561010090810261ff0019921515831661ffff1998891617178b5593518a89015591516002998a01805492511515850291151584169287169290921717905595516001600160a01b031682529681208054909516909617845592909301805461010193169290921790915591620005d36005546001600160a01b031690565b6001600160a01b039081168252602080830193909352604091820160009081206002908101805496151560ff1997881617905589850151831682526027909452828120840180548616600190811790915560065483168252929020909201805490931617909155600880549188166001600160a01b0319909216919091179055607860235562000663856200091a565b6200069060006200067c6005546001600160a01b031690565b838f6200068a919062000fa9565b6200098d565b505050505050505050505050620010b8565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6020820151825160408401516200070c91906200108c565b6200071891906200108c565b6080830181905260000362000734576000606083015262000750565b8160600151826080018181516200074c91906200108c565b9052505b6020810151815160408301516200076891906200108c565b6200077491906200108c565b60808201819052600003620007905760006060820152620007ac565b806060015181608001818151620007a891906200108c565b9052505b600782608001511180620007c4575060078160800151115b15620007e35760405163c52a9bd360e01b815260040160405180910390fd5b5050565b6001600160a01b038316620008165780600260008282546200080a91906200108c565b909155506200088a9050565b6001600160a01b038316600090815260208190526040902054818110156200086b5760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401620000d3565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b038216620008a857600280548290039055620008c7565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516200090d91815260200190565b60405180910390a3505050565b805160005b818110156200098857600160276000858481518110620009435762000943620010a2565b6020908102919091018101516001600160a01b0316825281019190915260400160002060020180549115156101000261ff00199092169190911790556001016200091f565b505050565b6200099a838383620007e7565b6001600160a01b03831660009081526027602052604090206002015460ff1662000a4b576006546001600160a01b031663e30443bc84620009f0816001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801562000a3757600080fd5b505af192505050801562000a49575060015b505b6001600160a01b03821660009081526027602052604090206002015460ff1662000988576006546001600160a01b031663e30443bc8362000aa1816001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801562000ae857600080fd5b505af192505050801562000afa575060015b156200098857505050565b6123e98062004b4083390190565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b038111828210171562000b4e5762000b4e62000b13565b60405290565b604051601f8201601f191681016001600160401b038111828210171562000b7f5762000b7f62000b13565b604052919050565b600060a0828403121562000b9a57600080fd5b62000ba462000b29565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015292915050565b80516001600160a01b038116811462000bf057600080fd5b919050565b60006080828403121562000c0857600080fd5b604051608081016001600160401b038111828210171562000c2d5762000c2d62000b13565b60405290508062000c3e8362000bd8565b815262000c4e6020840162000bd8565b602082015262000c616040840162000bd8565b604082015262000c746060840162000bd8565b60608201525092915050565b600060a0828403121562000c9357600080fd5b62000c9d62000b29565b905062000caa8262000bd8565b81526020820151602082015260408201516040820152606082015160608201526080820151608082015292915050565b6000806000806000806000806000806103208b8d03121562000cfb57600080fd5b8a51995062000d0e8c60208d0162000b87565b985062000d1f8c60c08d0162000b87565b97506101608b015196506101808b0151955062000d406101a08c0162000bd8565b945062000d516101c08c0162000bd8565b6101e08c01519094506001600160401b038082111562000d7057600080fd5b818d0191508d601f83011262000d8557600080fd5b81518181111562000d9a5762000d9a62000b13565b62000dab60208260051b0162000b54565b91508181835260208301925060208260051b85010191508f82111562000dd057600080fd5b6020840193505b8184101562000dfd5762000deb8462000bd8565b83526020938401939092019162000dd7565b8096505050505062000e148c6102008d0162000bf5565b915062000e268c6102808d0162000c80565b90509295989b9194979a5092959850565b600181811c9082168062000e4c57607f821691505b60208210810362000e6d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000988576000816000526020600020601f850160051c8101602086101562000e9e5750805b601f850160051c820191505b8181101562000ebf5782815560010162000eaa565b505050505050565b81516001600160401b0381111562000ee35762000ee362000b13565b62000efb8162000ef4845462000e37565b8462000e73565b602080601f83116001811462000f33576000841562000f1a5750858301515b600019600386901b1c1916600185901b17855562000ebf565b600085815260208120601f198616915b8281101562000f645788860151825594840194600190910190840162000f43565b508582101562000f835787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000fbf5762000fbf62000f93565b92915050565b6001600160a01b03871681526020808201879052610100820190604083018760005b60038110156200100957815160ff168352918301919083019060010162000fe7565b505050508460a08301528360c08301528260e0830152979650505050505050565b6000602082840312156200103d57600080fd5b620010488262000bd8565b9392505050565b808202811582820484141762000fbf5762000fbf62000f93565b6000826200108757634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562000fbf5762000fbf62000f93565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161010051610120516139cf62001171600039600081816106c101528181611160015261120c015260008181610c58015261125a0152600081816108150152612eb80152600081816107c10152612f2b015260008181610a3f015281816110d60152818161119201528181611234015281816125b10152818161295501526129d70152600081816104d801528181610f4201528181611dd00152818161328c015261334401526139cf6000f3fe6080604052600436106104355760003560e01c80638da5cb5b11610229578063cde516271161012e578063ebdfd722116100b6578063f8ce58941161007a578063f8ce589414610d95578063f8f9892814610db5578063f954662114610dd5578063f9f4bfdd14610deb578063f9f94e3414610e0b57600080fd5b8063ebdfd72214610d13578063ec3a1d4b14610d29578063f2fde38b14610d3f578063f66a79a014610d5f578063f8b45b0514610d7f57600080fd5b8063e0f3ccf5116100fd578063e0f3ccf514610c7a578063e2f4560514610ca1578063e4748b9e14610cb7578063e7fa67e514610cde578063ea8a1af014610cfe57600080fd5b8063cde5162714610bc0578063d9cc0f3e14610be0578063dd62ed3e14610c00578063de35eb2414610c4657600080fd5b8063a9278a99116101b1578063c275c23111610180578063c275c23114610b26578063c408050614610b46578063c49b9a8014610b66578063caee544014610b86578063cb29813c14610ba057600080fd5b8063a9278a9914610a81578063bb44f3ac14610aa1578063bee0d6ad14610ac1578063bf56b37114610b1057600080fd5b80639a82a09a116101f85780639a82a09a146109bd5780639ff77da4146109e0578063a771654514610a0d578063a8aa1b3114610a2d578063a9059cbb14610a6157600080fd5b80638da5cb5b146109545780638ebfc7961461097257806395d89b411461099257806396792669146109a757600080fd5b806342966c681161033a5780636ddd1713116102c2578063838420131161028657806383842013146108bb57806383ebc78d146108dd578063857d81c9146108f357806388cda87314610913578063893fea8b1461093457600080fd5b80636ddd17131461083757806370a0823114610851578063715018a614610871578063719ce73e146108865780638183b3c8146108a657600080fd5b80635302750111610309578063530275011461077c57806354fd4d501461079b5780636101f1f8146107af5780636402511e146107e357806367dd01791461080357600080fd5b806342966c68146107035780634a829e79146107235780634b78286a14610742578063524513d61461076257600080fd5b806324dcfb37116103bd578063313ce5671161038c578063313ce5671461065757806332a8db871461067957806334303bcd1461068f5780633675f29b146106af5780633c191403146106e357600080fd5b806324dcfb37146105ec5780632b112e491461060c5780632ed6a367146106215780632ffe729a1461064157600080fd5b80631694505e116104045780631694505e146104c65780631732cded1461051257806318160ddd146105365780631959a0021461054b57806323b872dd146105cc57600080fd5b80630124043a1461044157806301339c211461046357806306fdde031461046b578063095ea7b31461049657600080fd5b3661043c57005b600080fd5b34801561044d57600080fd5b5061046161045c36600461342c565b610e2b565b005b610461610ed4565b34801561047757600080fd5b50610480611316565b60405161048d9190613465565b60405180910390f35b3480156104a257600080fd5b506104b66104b13660046134b4565b6113a8565b604051901515815260200161048d565b3480156104d257600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161048d565b34801561051e57600080fd5b50610528600d5481565b60405190815260200161048d565b34801561054257600080fd5b50600254610528565b34801561055757600080fd5b5061059e6105663660046134e0565b60276020526000908152604090208054600182015460029092015460ff80831693610100938490048216939092808316929190041685565b604080519515158652931515602086015292840191909152151560608301521515608082015260a00161048d565b3480156105d857600080fd5b506104b66105e7366004613504565b6113c2565b3480156105f857600080fd5b50610461610607366004613545565b6113e6565b34801561061857600080fd5b50610528611450565b34801561062d57600080fd5b5061046161063c36600461355e565b61146f565b34801561064d57600080fd5b50610528600b5481565b34801561066357600080fd5b5060095b60405160ff909116815260200161048d565b34801561068557600080fd5b5061052860225481565b34801561069b57600080fd5b506104616106aa3660046135d3565b6114df565b3480156106bb57600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ef57600080fd5b506104616106fe3660046135f9565b61151d565b34801561070f57600080fd5b5061046161071e366004613545565b611596565b34801561072f57600080fd5b50600c546104b690610100900460ff1681565b34801561074e57600080fd5b5061046161075d3660046134e0565b61168b565b34801561076e57600080fd5b506025546104b69060ff1681565b34801561078857600080fd5b506025546104b690610100900460ff1681565b3480156107a757600080fd5b506001610667565b3480156107bb57600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107ef57600080fd5b506104616107fe366004613545565b6116b5565b34801561080f57600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b34801561084357600080fd5b50600e546104b69060ff1681565b34801561085d57600080fd5b5061052861086c3660046134e0565b6116c2565b34801561087d57600080fd5b506104616116dd565b34801561089257600080fd5b506006546104fa906001600160a01b031681565b3480156108b257600080fd5b506104616116f1565b3480156108c757600080fd5b506025546104b690640100000000900460ff1681565b3480156108e957600080fd5b5061052860215481565b3480156108ff57600080fd5b5061046161090e366004613625565b611719565b34801561091f57600080fd5b506025546104b6906301000000900460ff1681565b34801561094057600080fd5b506008546104fa906001600160a01b031681565b34801561096057600080fd5b506005546001600160a01b03166104fa565b34801561097e57600080fd5b5061046161098d36600461342c565b611753565b34801561099e57600080fd5b50610480611786565b3480156109b357600080fd5b5061052860115481565b3480156109c957600080fd5b506025546104b69065010000000000900460ff1681565b3480156109ec57600080fd5b506105286109fb366004613545565b60106020526000908152604090205481565b348015610a1957600080fd5b50610461610a28366004613658565b611795565b348015610a3957600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b348015610a6d57600080fd5b506104b6610a7c3660046134b4565b611867565b348015610a8d57600080fd5b50610461610a9c366004613545565b611875565b348015610aad57600080fd5b50610461610abc366004613545565b6118ae565b348015610acd57600080fd5b50601254601354601454601554601654610ae8949392919085565b604080519586526020860194909452928401919091526060830152608082015260a00161048d565b348015610b1c57600080fd5b5061052860095481565b348015610b3257600080fd5b50610461610b41366004613625565b6118bb565b348015610b5257600080fd5b50610461610b61366004613658565b6118d6565b348015610b7257600080fd5b50610461610b81366004613625565b611908565b348015610b9257600080fd5b50600c546104b69060ff1681565b348015610bac57600080fd5b50610461610bbb36600461371d565b611957565b348015610bcc57600080fd5b50610461610bdb366004613545565b611a4e565b348015610bec57600080fd5b50610461610bfb366004613545565b611a87565b348015610c0c57600080fd5b50610528610c1b366004613760565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b348015610c5257600080fd5b506105287f000000000000000000000000000000000000000000000000000000000000000081565b348015610c8657600080fd5b50601c54601d54601e54601f54602054610ae8949392919085565b348015610cad57600080fd5b50610528600f5481565b348015610cc357600080fd5b50601754601854601954601a54601b54610ae8949392919085565b348015610cea57600080fd5b50610461610cf9366004613545565b611ac0565b348015610d0a57600080fd5b50610461611af9565b348015610d1f57600080fd5b5061052860245481565b348015610d3557600080fd5b5061052860235481565b348015610d4b57600080fd5b50610461610d5a3660046134e0565b611ba5565b348015610d6b57600080fd5b506007546104fa906001600160a01b031681565b348015610d8b57600080fd5b50610528600a5481565b348015610da157600080fd5b50610461610db03660046134e0565b611be5565b348015610dc157600080fd5b50610461610dd0366004613658565b611caf565b348015610de157600080fd5b5061052860265481565b348015610df757600080fd5b506025546104b69062010000900460ff1681565b348015610e1757600080fd5b50610461610e263660046134e0565b611d16565b610e33611d50565b6001600160a01b038281166000908152602760205260409020600201805460ff19168315151790556006541663fd8703608383610e6f826116c2565b6040516001600160e01b031960e086901b1681526001600160a01b03909316600484015290151560248301526044820152606401600060405180830381600087803b158015610ebd57600080fd5b505af1925050508015610ece575060015b505b5050565b610edc611d50565b6002600d55600954151580610efc575060255465010000000000900460ff165b15610f1a5760405163c52a9bd360e01b815260040160405180910390fd5b426009819055602354610f2c916137a4565b6024556025805460ff19166001179055610f69307f0000000000000000000000000000000000000000000000000000000000000000600019611d7d565b610f85610f75306116c2565b610f7f34476137b7565b30611d8a565b50600854604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018187875af1158015610fd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff591906137ca565b6110009060016137a4565b905060015b818110156110bd576008546040516331a9108f60e11b8152600481018390526001916027916000916001600160a01b031690636352211e906024016020604051808303816000875af115801561105f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108391906137e3565b6001600160a01b03168152602081019190915260400160002060020180549115156101000261ff0019909216919091179055600101611005565b506040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611125573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114991906137ca565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af11580156111dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112019190613800565b506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016635af06fed347f0000000000000000000000000000000000000000000000000000000000000000338561127f7f0000000000000000000000000000000000000000000000000000000000000000426137a4565b6040516001600160e01b031960e088901b1681526001600160a01b0394851660048201529390921660248401526044830152606482015260006084820181905260a482015260c40160206040518083038185885af11580156112e5573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061130a91906137ca565b60265550506001600d55565b6060600380546113259061381d565b80601f01602080910402602001604051908101604052809291908181526020018280546113519061381d565b801561139e5780601f106113735761010080835404028352916020019161139e565b820191906000526020600020905b81548152906001019060200180831161138157829003601f168201915b5050505050905090565b6000336113b6818585611d7d565b60019150505b92915050565b6000336113d0858285611e4b565b6113db858585611ec9565b506001949350505050565b6113ee611d50565b6006546040516324dcfb3760e01b8152600481018390526001600160a01b03909116906324dcfb37906024015b600060405180830381600087803b15801561143557600080fd5b505af1158015611449573d6000803e3d6000fd5b5050505050565b600061145d61dead6116c2565b60025461146a91906137b7565b905090565b611477611d50565b600654604051632ed6a36760e01b81526001600160a01b0390911690632ed6a367906114a99085908590600401613857565b600060405180830381600087803b1580156114c357600080fd5b505af11580156114d7573d6000803e3d6000fd5b505050505050565b6114e7611d50565b6006546040516334303bcd60e01b815263ffffffff831660048201526001600160a01b03909116906334303bcd9060240161141b565b611525611d50565b600654604051633c19140360e01b81526004810185905260248101849052604481018390526001600160a01b0390911690633c19140390606401600060405180830381600087803b15801561157957600080fd5b505af115801561158d573d6000803e3d6000fd5b50505050505050565b6115a03382611f28565b3360009081526027602052604090206002015460ff1661168857600654604051632770a7eb60e21b8152336004820152602481018390526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b15801561160657600080fd5b505af1925050508015611617575060015b506006546001600160a01b031663e30443bc33611633816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561167957600080fd5b505af1925050508015610ed057505b50565b611693611d50565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b6116bd611d50565b600f55565b6001600160a01b031660009081526020819052604090205490565b6116e5611d50565b6116ef6000611f5e565b565b6116f9611d50565b6116ef303360165461170a306116c2565b61171491906137b7565b611fb0565b611721611d50565b60065460405163857d81c960e01b815282151560048201526001600160a01b039091169063857d81c99060240161141b565b61175b611d50565b6001600160a01b03919091166000908152602760205260409020805460ff1916911515919091179055565b6060600480546113259061381d565b61179d611d50565b805160005b81811015610ece5760065483516001600160a01b039091169063fd870360908590849081106117d3576117d3613890565b602002602001015160016117ff8786815181106117f2576117f2613890565b60200260200101516116c2565b6040516001600160e01b031960e086901b1681526001600160a01b03909316600484015290151560248301526044820152606401600060405180830381600087803b15801561184d57600080fd5b505af192505050801561185e575060015b506001016117a2565b6000336113b6818585611ec9565b61187d611d50565b60065460405163a9278a9960e01b8152600481018390526001600160a01b039091169063a9278a999060240161141b565b6118b6611d50565b601155565b6118c3611d50565b600c805460ff1916911515919091179055565b6118de611d50565b600954156118ff5760405163c52a9bd360e01b815260040160405180910390fd5b611688816120f1565b611910611d50565b600e805460ff19168215159081179091556040519081527f53726dfcaf90650aa7eb35524f4d3220f07413c8d6cb404cc8c18bf5591bc1599060200160405180910390a150565b61195f611d50565b602554610100900460ff16158061197f575060255462010000900460ff16155b1561199d5760405163c52a9bd360e01b815260040160405180910390fd5b6119a56133ca565b60408101879052858152602081018590526119be6133ca565b60408101859052838152602081018390526009546000036119e1576002806119e9565b6119e961215a565b6060838101919091528301526119ff82826121cc565b8151601755602080830151601855604080840151601955606080850151601a55608094850151601b558351601c5583830151601d5590830151601e55820151601f559101519055505050505050565b611a56611d50565b60065460405163cde5162760e01b8152600481018390526001600160a01b039091169063cde516279060240161141b565b611a8f611d50565b600654604051636ce6079f60e11b8152600481018390526001600160a01b039091169063d9cc0f3e9060240161141b565b611ac8611d50565b60065460405163e7fa67e560e01b8152600481018390526001600160a01b039091169063e7fa67e59060240161141b565b611b01611d50565b60095415611b225760405163c52a9bd360e01b815260040160405180910390fd5b6025805465ff0000000000191665010000000000179055611b5830611b4f6005546001600160a01b031690565b611714306116c2565b6005546040516001600160a01b03909116904790600081818185875af1925050503d8060008114610ece576040519150601f19603f3d011682016040523d82523d6000602084013e505050565b611bad611d50565b6001600160a01b038116611bdc57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61168881611f5e565b611bed611d50565b6006546001600160a01b0390811690821603611c0857600080fd5b6000819050306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7991906137e3565b6001600160a01b031614611c8c57600080fd5b600680546001600160a01b0319166001600160a01b039290921691909117905550565b611cb7611d50565b805160005b81811015610ece57600160276000858481518110611cdc57611cdc613890565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101611cbc565b611d1e611d50565b600654604051633e7e538d60e21b81526001600160a01b0383811660048301529091169063f9f94e349060240161141b565b6005546001600160a01b031633146116ef5760405163118cdaa760e01b8152336004820152602401611bd3565b610ece83838360016122a9565b60405163f305d71960e01b815230600482015260248101849052600060448201819052606482018190526001600160a01b0383811660848401524260a4840152909182917f0000000000000000000000000000000000000000000000000000000000000000169063f305d71990869060c40160606040518083038185885af1158015611e1a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e3f91906138a6565b50909695505050505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114611ec35781811015611eb457604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401611bd3565b611ec3848484840360006122a9565b50505050565b6001600160a01b038316611ef357604051634b637e8f60e11b815260006004820152602401611bd3565b6001600160a01b038216611f1d5760405163ec442f0560e01b815260006004820152602401611bd3565b610ece83838361237e565b6001600160a01b038216611f5257604051634b637e8f60e11b815260006004820152602401611bd3565b610ed08260008361237e565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611fbb838383612b8b565b6001600160a01b03831660009081526027602052604090206002015460ff16612052576006546001600160a01b031663e30443bc84611ff9816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561203f57600080fd5b505af1925050508015612050575060015b505b6001600160a01b03821660009081526027602052604090206002015460ff16610ece576006546001600160a01b031663e30443bc83612090816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156120d657600080fd5b505af19250505080156120e7575060015b15610ece57505050565b805160005b81811015610ece5760016027600085848151811061211657612116613890565b6020908102919091018101516001600160a01b0316825281019190915260400160002060020180549115156101000261ff00199092169190911790556001016120f6565b60008060006009544261216d91906137b7565b90506228de808111156121995750506025805464ff000000001916640100000000179055506000908190565b620151808111156121c15750506025805463ff00000019166301000000179055506001908190565b506002928392509050565b6020820151825160408401516121e291906137a4565b6121ec91906137a4565b608083018190526000036122065760006060830152612220565b81606001518260800181815161221c91906137a4565b9052505b60208101518151604083015161223691906137a4565b61224091906137a4565b6080820181905260000361225a5760006060820152612274565b80606001518160800181815161227091906137a4565b9052505b60078260800151118061228b575060078160800151115b15610ed05760405163c52a9bd360e01b815260040160405180910390fd5b6001600160a01b0384166122d35760405163e602df0560e01b815260006004820152602401611bd3565b6001600160a01b0383166122fd57604051634a1406b160e11b815260006004820152602401611bd3565b6001600160a01b0380851660009081526001602090815260408083209387168352929052208290558015611ec357826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161237091815260200190565b60405180910390a350505050565b600d546002148061239c57506005546001600160a01b038481169116145b806123b457506005546001600160a01b038381169116145b806123c757506001600160a01b03831630145b806123da57506001600160a01b03821630145b806123e3575080155b156123f357610ece838383611fb0565b600954600003612416576040516312f1f92360e01b815260040160405180910390fd5b6001600160a01b038084166000908152602760205260408082209285168252902060255460ff161561249d57602454421015612492576002820154610100900460ff16158061246f57506002810154610100900460ff16155b1561248d57604051630b094f2760e31b815260040160405180910390fd5b61249d565b6025805460ff191690555b600c54610100900460ff1661253c576000600954426124bc91906137b7565b905060006124cb6078836138d4565b6124d69060646138f6565b600b546124e391906137a4565b90506103b68111156125035750600c805461ff0019166101001790556103e85b6000620186a08261251360025490565b61251d91906138f6565b61252791906138d4565b9050600a54811461253857600a8190555b5050505b600c5460ff161561258f578054610100900460ff161580156125715750600a54612565856116c2565b61256f90856137a4565b115b1561258f5760405163fd42866160e01b815260040160405180910390fd5b601654600f54811080159081906125a85750600e5460ff165b80156125e657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614155b8015612602575060115443600090815260106020526040902054105b156126365743600090815260106020526040812080549091906126249061390d565b90915550600f54612636908390612cb5565b835460ff1615801561264a5750825460ff16155b15612a7457602554601790601c90640100000000900460ff166129515760006009544261267791906137b7565b6025549091506301000000900460ff1615801561269657506201518081115b15612749576000836003015484600401546126b191906137b7565b9050806000036126ce5760006004850181905560038501556126e5565b83546126db9060016137a4565b8455600160038501555b6000836003015484600401546126fb91906137b7565b90508060000361271857600060048501819055600385015561272f565b83546127259060016137a4565b8455600160038501555b50506025805463ff0000001916630100000017905561294f565b6228de808111156127b457826003015483600001600082825461276c91906137a4565b90915550506003820154825483906000906127889084906137a4565b9091555050600060038085018290558301556025805464ff00000000191664010000000017905561294f565b602554610100900460ff1661288057602154806107098310156127ea576127dc6078846138d4565b6127e790600f6137b7565b90505b81811161283b576004850182905560038501548554600287015461280e90856137b7565b61281891906137b7565b61282291906137b7565b60018601556025805461ff00191661010017905561287d565b8460040154811461287d576004850181905560038501548554600287015461286390846137b7565b61286d91906137b7565b61287791906137b7565b60018601555b50505b60255462010000900460ff1661294f57602254806109618310156128b7576128a96078846138d4565b6128b49060146137b7565b90505b81811161290a57600484018290556003840154845460028601546128db90856137b7565b6128e591906137b7565b6128ef91906137b7565b60018501556025805462ff000019166201000017905561294c565b8360040154811461294c576004840181905560038401548454600286015461293290846137b7565b61293c91906137b7565b61294691906137b7565b60018501555b50505b505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b0316036129d5576040805160a081018252835481526001840154602082015260028401549181019190915260038301546060820152600483015460808201526129ce9089613108565b9050612a53565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168a6001600160a01b031603612a53576040805160a08101825284548152600185015460208201526002850154918101919091526003840154606082015260048401546080820152612a509089613108565b90505b8015612a7057612a6381896137b7565b9750612a708a3083612b8b565b5050505b612a7f878787612b8b565b600284015460ff16612aff576006546001600160a01b031663e30443bc88612aa6816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015612aec57600080fd5b505af1925050508015612afd575060015b505b600283015460ff1661158d576006546001600160a01b031663e30443bc87612b26816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015612b6c57600080fd5b505af1925050508015612b7d575060015b1561158d5750505050505050565b6001600160a01b038316612bb6578060026000828254612bab91906137a4565b90915550612c289050565b6001600160a01b03831660009081526020819052604090205481811015612c095760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401611bd3565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b038216612c4457600280548290039055612c63565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612ca891815260200190565b60405180910390a3505050565b6002600d556012612cc46133ca565b81548490612cd290856138f6565b612cdc91906138d4565b815260018201548490612cef90856138f6565b612cf991906138d4565b602082015260028201548490612d0f90856138f6565b612d1991906138d4565b604082015260038201548490612d2f90856138f6565b612d3991906138d4565b60608201526040810151600090612d52906002906138d4565b9050612d5e81856137b7565b60808301819052600090612d719061322f565b9050612d7b6133ca565b60808401518451612d8c90846138f6565b612d9691906138d4565b80825215612df45760065481516040516001600160a01b0390921691600081818185875af1925050503d8060008114612deb576040519150601f19603f3d011682016040523d82523d6000602084013e612df0565b606091505b5050505b60808401516020850151612e0890846138f6565b612e1291906138d4565b6020820181905215612e775760075460208201516040516001600160a01b0390921691600081818185875af1925050503d8060008114612e6e576040519150601f19603f3d011682016040523d82523d6000602084013e612e73565b606091505b5050505b60808401516060850151612e8b90846138f6565b612e9591906138d4565b6060820181905215612fa957600060028260600151612eb491906138d4565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168160405160006040518083038185875af1925050503d8060008114612f21576040519150601f19603f3d011682016040523d82523d6000602084013e612f26565b606091505b5050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316818360600151612f6391906137b7565b604051600081818185875af1925050503d8060008114612f9f576040519150601f19603f3d011682016040523d82523d6000602084013e612fa4565b606091505b505050505b47604082015260008315801590612fc4575060008260400151115b1561302357612fda84836040015161dead611d8a565b90507f28fc98272ce761178794ad6768050fea1648e07f1e2ffe15afd3a290f838148684836040015160405161301a929190918252602082015260400190565b60405180910390a15b600061302f82866137b7565b866040015161303e91906137b7565b9050856000015187600001600082825461305891906137b7565b909155505060208601516001880180546000906130769084906137b7565b925050819055508087600201600082825461309191906137b7565b909155505060608601516003880180546000906130af9084906137b7565b90915550506060860151602087015187518392916130cc916137a4565b6130d691906137a4565b6130e091906137a4565b8760040160008282546130f391906137b7565b90915550506001600d55505050505050505050565b600082608001516000146113bc57606483608001518361312891906138f6565b61313291906138d4565b6080840151845191925060129161314990846138f6565b61315391906138d4565b81600001600082825461316691906137a4565b90915550506080840151602085015161317f90846138f6565b61318991906138d4565b81600101600082825461319c91906137a4565b9091555050608084015160408501516131b590846138f6565b6131bf91906138d4565b8160020160008282546131d291906137a4565b9091555050608084015160608501516131eb90846138f6565b6131f591906138d4565b81600301600082825461320891906137a4565b925050819055508181600401600082825461322391906137a4565b90915550505092915050565b604080516002808252606082018352600092479284929091602083019080368337019050509050308160008151811061326a5761326a613890565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330c91906137e3565b8160018151811061331f5761331f613890565b6001600160a01b03928316602091820292909201015260405163791ac94760e01b81527f00000000000000000000000000000000000000000000000000000000000000009091169063791ac94790613384908790600090869030904290600401613926565b600060405180830381600087803b15801561339e57600080fd5b505af11580156133b2573d6000803e3d6000fd5b5050505081476133c291906137b7565b949350505050565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b038116811461168857600080fd5b8035613419816133f9565b919050565b801515811461168857600080fd5b6000806040838503121561343f57600080fd5b823561344a816133f9565b9150602083013561345a8161341e565b809150509250929050565b60006020808352835180602085015260005b8181101561349357858101830151858201604001528201613477565b506000604082860101526040601f19601f8301168501019250505092915050565b600080604083850312156134c757600080fd5b82356134d2816133f9565b946020939093013593505050565b6000602082840312156134f257600080fd5b81356134fd816133f9565b9392505050565b60008060006060848603121561351957600080fd5b8335613524816133f9565b92506020840135613534816133f9565b929592945050506040919091013590565b60006020828403121561355757600080fd5b5035919050565b6000806020838503121561357157600080fd5b823567ffffffffffffffff8082111561358957600080fd5b818501915085601f83011261359d57600080fd5b8135818111156135ac57600080fd5b8660208260051b85010111156135c157600080fd5b60209290920196919550909350505050565b6000602082840312156135e557600080fd5b813563ffffffff811681146134fd57600080fd5b60008060006060848603121561360e57600080fd5b505081359360208301359350604090920135919050565b60006020828403121561363757600080fd5b81356134fd8161341e565b634e487b7160e01b600052604160045260246000fd5b6000602080838503121561366b57600080fd5b823567ffffffffffffffff8082111561368357600080fd5b818501915085601f83011261369757600080fd5b8135818111156136a9576136a9613642565b8060051b604051601f19603f830116810181811085821117156136ce576136ce613642565b6040529182528482019250838101850191888311156136ec57600080fd5b938501935b82851015613711576137028561340e565b845293850193928501926136f1565b98975050505050505050565b60008060008060008060c0878903121561373657600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b6000806040838503121561377357600080fd5b823561377e816133f9565b9150602083013561345a816133f9565b634e487b7160e01b600052601160045260246000fd5b808201808211156113bc576113bc61378e565b818103818111156113bc576113bc61378e565b6000602082840312156137dc57600080fd5b5051919050565b6000602082840312156137f557600080fd5b81516134fd816133f9565b60006020828403121561381257600080fd5b81516134fd8161341e565b600181811c9082168061383157607f821691505b60208210810361385157634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252810182905260006001600160fb1b0383111561387757600080fd5b8260051b80856040850137919091016040019392505050565b634e487b7160e01b600052603260045260246000fd5b6000806000606084860312156138bb57600080fd5b8351925060208401519150604084015190509250925092565b6000826138f157634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176113bc576113bc61378e565b60006001820161391f5761391f61378e565b5060010190565b600060a08201878352602087602085015260a0604085015281875180845260c08601915060208901935060005b818110156139785784516001600160a01b031683529383019391830191600101613953565b50506001600160a01b0396909616606085015250505060800152939250505056fea264697066735822122002c2c1ccb3925245c3b4ebd15cb3bf4cf80c78612ea7c61b5d65022b02a8b7b464736f6c6343000818003360a0604052600060049081556006557f8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef600b55600c805466ffffffffffffff1916640300e4e1c01790553480156200005657600080fd5b50604051620023e9380380620023e9833981016040819052620000799162000413565b6001600160a01b0386166080523380620000ad57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b620000b88162000396565b50600380546001600160a01b03191633179055604084015160208501518551620000e39190620004fe565b620000ef9190620004fe565b60ff16606414620001135760405163c52a9bd360e01b815260040160405180910390fd5b6040805160808082018352858252620151806020808401918252885160ff90811685870190815260006060808801828152828052600280875298517fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b5595517fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077c5591517fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077d5593517fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077e55865180860188528a815262093a808185019081528c8501518416828a019081528284018781526001885289875292517fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e05590517fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e155517fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e255517fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e3558651948501875289855262278d008584019081528b88015190921696850196875284018381529285905293905290517f679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28c5590517f679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28d5590517f679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28e55517f679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28f55600d819055600980546001600160a01b0319166001600160a01b03881617905560088590556200038682610e1062000520565b600455506200053a945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b634e487b7160e01b600052604160045260246000fd5b805160ff811681146200040e57600080fd5b919050565b60008060008060008061010087890312156200042e57600080fd5b86516001600160a01b03811681146200044657600080fd5b80965050602080880151955088605f8901126200046257600080fd5b604051606081016001600160401b0381118282101715620004875762000487620003e6565b6040528060a08a018b8111156200049d57600080fd5b60408b015b81811015620004c457620004b681620003fc565b8352918401918401620004a2565b50829750805196505050505060c0870151915060e087015190509295509295509295565b634e487b7160e01b600052601160045260246000fd5b60ff81811683821601908111156200051a576200051a620004e8565b92915050565b80820281158282048414176200051a576200051a620004e8565b608051611e8c6200055d600039600081816109a401526109e60152611e8c6000f3fe6080604052600436106101dc5760003560e01c80638da5cb5b11610102578063dacfa83011610095578063eddad39411610064578063eddad39414610708578063f2fde38b1461076c578063f9f94e341461078c578063fd870360146107ac57600080fd5b8063dacfa83014610685578063dd11247e146106b2578063e30443bc146106c8578063e7fa67e5146106e857600080fd5b8063a9278a99116100d1578063a9278a9914610605578063aeefe31f14610625578063cde5162714610645578063d9cc0f3e1461066557600080fd5b80638da5cb5b146105915780639d2bc0c2146105af5780639dc29fac146105c5578063a694fc3a146105e557600080fd5b80632ed6a3671161017a57806354ed61741161014957806354ed61741461050e5780636ecf9f7b14610524578063715018a61461055c578063857d81c91461057157600080fd5b80632ed6a3671461049857806334303bcd146104b85780633939a897146104d85780633c191403146104ee57600080fd5b80631aa3a008116101b65780631aa3a008146104235780631fe543e31461043857806324dcfb37146104585780632e17de781461047857600080fd5b80630484a22f1461035d5780630eecae21146103b65780631959a002146103cd57600080fd5b36610358576000600754346101f19190611a51565b6002602081905260009081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077d549192507fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b917fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0917f679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28c916064906102959087611a6a565b61029f9190611a97565b9050600060648460020154876102b59190611a6a565b6102bf9190611a97565b9050600060648460020154886102d59190611a6a565b6102df9190611a97565b9050828660030160008282546102f59190611a51565b92505081905550818560030160008282546103109190611a51565b925050819055508084600301600082825461032b9190611a51565b909155508190508261033d858a611aab565b6103479190611aab565b6103519190611aab565b6007819055005b600080fd5b34801561036957600080fd5b506103a3610378366004611ada565b6001600160a01b03166000908152600160209081526040808320601154845260020190915290205490565b6040519081526020015b60405180910390f35b3480156103c257600080fd5b506103cb6107cc565b005b3480156103d957600080fd5b506104086103e8366004611ada565b600160208190526000918252604090912080549181015460039091015483565b604080519384526020840192909252908201526060016103ad565b34801561042f57600080fd5b506103cb61091e565b34801561044457600080fd5b506103cb610453366004611b0b565b610999565b34801561046457600080fd5b506103cb610473366004611bd5565b610a26565b34801561048457600080fd5b506103cb610493366004611bd5565b610a75565b3480156104a457600080fd5b506103cb6104b3366004611bee565b610b23565b3480156104c457600080fd5b506103cb6104d3366004611c63565b610cbe565b3480156104e457600080fd5b506103a360065481565b3480156104fa57600080fd5b506103cb610509366004611c89565b610ce2565b34801561051a57600080fd5b506103a3600d5481565b34801561053057600080fd5b50600354610544906001600160a01b031681565b6040516001600160a01b0390911681526020016103ad565b34801561056857600080fd5b506103cb610cf5565b34801561057d57600080fd5b506103cb61058c366004611cc5565b610d07565b34801561059d57600080fd5b506000546001600160a01b0316610544565b3480156105bb57600080fd5b506103a360045481565b3480156105d157600080fd5b506103cb6105e0366004611ce0565b610d33565b3480156105f157600080fd5b506103cb610600366004611bd5565b610d7c565b34801561061157600080fd5b506103cb610620366004611bd5565b610dce565b34801561063157600080fd5b506103a3610640366004611ada565b610ddb565b34801561065157600080fd5b506103cb610660366004611bd5565b610e8f565b34801561067157600080fd5b506103cb610680366004611bd5565b610e9c565b34801561069157600080fd5b506103a36106a0366004611bd5565b600f6020526000908152604090205481565b3480156106be57600080fd5b506103a3600e5481565b3480156106d457600080fd5b506103cb6106e3366004611ce0565b610eb6565b3480156106f457600080fd5b506103cb610703366004611bd5565b610ec8565b34801561071457600080fd5b5061074c610723366004611bd5565b600260208190526000918252604090912080546001820154928201546003909201549092919084565b6040805194855260208501939093529183015260608201526080016103ad565b34801561077857600080fd5b506103cb610787366004611ada565b610ed5565b34801561079857600080fd5b506103cb6107a7366004611ada565b610f10565b3480156107b857600080fd5b506103cb6107c7366004611d0a565b610f3a565b600c546601000000000000900460ff16156107fa576040516360d032a960e11b815260040160405180910390fd5b61080660056000611a09565b6004546000904290825b60038110156108cb57600081815260026020526040902060018101548154429161083991611a51565b1115801561084a5750600381015415155b156108c2578261085d6201518086611d46565b6108679086611aab565b6108719190611a51565b6000838152600260205260408120919091556005805460018101825591527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001829055846108be81611d5a565b9550505b50600101610810565b508215806108d95750600e54155b156108f757604051633620f14360e01b815260040160405180910390fd5b600c546109199063ffffffff811690640100000000900461ffff166001610f5d565b505050565b6003546040516370a0823160e01b815233600482018190526109979290916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561096e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109929190611d73565b611032565b565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a185760405163073e64fd60e21b81523360048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b610a2282826110da565b5050565b610a2e6110fd565b633b9aca00811015610a535760405163c52a9bd360e01b815260040160405180910390fd5b600d81905560118054906000610a6883611d5a565b90915550506000600e5550565b33600090815260016020526040902060030154610a959062093a80611a51565b421015610ab557604051630a68850160e11b815260040160405180910390fd5b33600090815260016020526040902054811115610ae55760405163263892ab60e01b815260040160405180910390fd5b3360009081526001602052604081208054839290610b04908490611aab565b9091555050600354610b20906001600160a01b0316338361112a565b50565b610b2b6110fd565b600381141580610b6157506201518082826000818110610b4d57610b4d611d8c565b90506020020135610b5e9190611d46565b15155b80610b9257506201518082826001818110610b7e57610b7e611d8c565b90506020020135610b8f9190611d46565b15155b80610bc357506201518082826002818110610baf57610baf611d8c565b90506020020135610bc09190611d46565b15155b15610be15760405163c52a9bd360e01b815260040160405180910390fd5b81816000818110610bf457610bf4611d8c565b60008052600260209081520291909101357fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077c555081816001818110610c3b57610c3b611d8c565b60016000526002602081815290910292909201357fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e1555082908290818110610c8557610c85611d8c565b6002600081905260209081520291909101357f679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28d55505050565b610cc66110fd565b600c805463ffffffff191663ffffffff92909216919091179055565b610cea6110fd565b610919838383611189565b610cfd6110fd565b6109976000611239565b610d0f6110fd565b600c805491151566010000000000000266ff00000000000019909216919091179055565b610d3b6110fd565b600654610d489082611a6a565b6001600160a01b03831660009081526001602081905260408220018054909190610d73908490611a51565b90915550505050565b3360009081526001602052604081208054839290610d9b908490611a51565b90915550503360008181526001602052604090204260039182015554610b20916001600160a01b03909116903084611289565b610dd66110fd565b600655565b6001600160a01b03811660009081526001602081905260408220908101548154610e06906002611a6a565b6003546040516370a0823160e01b81526001600160a01b038781166004830152909116906370a0823190602401602060405180830381865afa158015610e50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e749190611d73565b610e7e9190611a51565b610e889190611a51565b9392505050565b610e976110fd565b600855565b610ea46110fd565b610eb081610e10611a6a565b60045550565b610ebe6110fd565b610a228282611032565b610ed06110fd565b600b55565b610edd6110fd565b6001600160a01b038116610f0757604051631e4fbdf760e01b815260006004820152602401610a0f565b610b2081611239565b610f186110fd565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b610f426110fd565b8115610f53576109198360006112c8565b6109198382611032565b6000610f796040518060200160405280600015158152506115bc565b6040805160c081018252600b548152600854602082015261ffff86168183015263ffffffff80881660608301528516608082015260a081018390526009549151634d8e1c2f60e11b8152929350916001600160a01b0390911690639b1c385e90610fe7908490600401611da2565b6020604051808303816000875af1158015611006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102a9190611d73565b505050505050565b6001600160a01b03821660009081526001602081905260408220601154600d54928201548254929491939192611069906002611a6a565b6110739087611a51565b61107d9190611a51565b6110879190611a97565b60008381526002850160205260409020549091508111156110b1576110ac858261162d565b6110d3565b60008281526002840160205260409020548110156110d3576110d385826112c8565b5050505050565b610a22816000815181106110f0576110f0611d8c565b6020026020010151611740565b6000546001600160a01b031633146109975760405163118cdaa760e01b8152336004820152602401610a0f565b6040516001600160a01b0383811660248301526044820183905261091991859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611998565b806111948385611a51565b61119e9190611a51565b6064146111be5760405163c52a9bd360e01b815260040160405180910390fd5b600260208190527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077d939093557fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e2919091556000919091527f679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28e55565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b0384811660248301528381166044830152606482018390526112c29186918216906323b872dd90608401611157565b50505050565b6001600160a01b03821660009081526001602090815260408083206011548085526002820190935290832054909290611302908590611aab565b60008381526010602052604081209192505b8281101561159c57815460009061132d90600190611aab565b600086815260028801602090815260408083208054825181850281018501909352808352949550929390929183018282801561138857602002820191906000526020600020905b815481526020019060010190808311611374575b505050505090506000600160008685815481106113a7576113a7611d8c565b60009182526020808320909101546001600160a01b03168352820192909252604001902085549091508590849081106113e2576113e2611d8c565b9060005260206000200160009054906101000a90046001600160a01b03168583600185516114109190611aab565b8151811061142057611420611d8c565b60200260200101518154811061143857611438611d8c565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600183516114759190611aab565b8151811061148557611485611d8c565b6020026020010151816002016000898152602001908152602001600020600f600086815260200190815260200160002054815481106114c6576114c6611d8c565b9060005260206000200181905550600f600084815260200190815260200160002054600f600084600186516114fb9190611aab565b8151811061150b5761150b611d8c565b602002602001015181526020019081526020016000208190555087600201600088815260200190815260200160002080548061154957611549611e40565b600190038181906000526020600020016000905590558480548061156f5761156f611e40565b600082815260209020810160001990810180546001600160a01b0319169055019055505050600101611314565b5081600e60008282546115af9190611aab565b9091555050505050505050565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa826040516024016115f591511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6001600160a01b038216600090815260016020908152604080832060115480855260028201909352908320549092906116669085611aab565b6000838152601060205260408120805492935091905b8381101561171f576000858152600287016020526040902061169e8284611a51565b8154600180820184556000938452602080852090920192909255855480830187558684528184200180546001600160a01b0319166001600160a01b038d161790558783526002890190526040909120546116f89190611aab565b600f60006117068486611a51565b815260208101919091526040016000205560010161167c565b5082600e60008282546117329190611a51565b909155505050505050505050565b6000600580548060200260200160405190810160405280929190818152602001828054801561178e57602002820191906000526020600020905b81548152602001906001019080831161177a575b5050505050905060008151905060008060005b8381101561102a576000600e5487856040516020016117ca929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c6117ed9190611d46565b9050836117f981611d5a565b94505060006002600088858151811061181457611814611d8c565b60200260200101518152602001908152602001600020600301549050601060006011548152602001908152602001600020828154811061185657611856611d8c565b60009182526020822001546040516001600160a01b039091169183919081818185875af1925050503d80600081146118aa576040519150601f19603f3d011682016040523d82523d6000602084013e6118af565b606091505b509094505083156118f0576000600260008986815181106118d2576118d2611d8c565b60200260200101518152602001908152602001600020600301819055505b7f3d210d5ae36955ded2bdf69bd956eb075b7fd07362288c7df1797cd8eb1199bf87848151811061192357611923611d8c565b6020026020010151601060006011548152602001908152602001600020848154811061195157611951611d8c565b60009182526020918290200154604080519384526001600160a01b039091169183019190915281018390526060810184905260800160405180910390a150506001016117a1565b600080602060008451602086016000885af1806119bb576040513d6000823e3d81fd5b50506000513d915081156119d35780600114156119e0565b6001600160a01b0384163b155b156112c257604051635274afe760e01b81526001600160a01b0385166004820152602401610a0f565b5080546000825590600052602060002090810190610b2091905b80821115611a375760008155600101611a23565b5090565b634e487b7160e01b600052601160045260246000fd5b80820180821115611a6457611a64611a3b565b92915050565b8082028115828204841417611a6457611a64611a3b565b634e487b7160e01b600052601260045260246000fd5b600082611aa657611aa6611a81565b500490565b81810381811115611a6457611a64611a3b565b80356001600160a01b0381168114611ad557600080fd5b919050565b600060208284031215611aec57600080fd5b610e8882611abe565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215611b1e57600080fd5b8235915060208084013567ffffffffffffffff80821115611b3e57600080fd5b818601915086601f830112611b5257600080fd5b813581811115611b6457611b64611af5565b8060051b604051601f19603f83011681018181108582111715611b8957611b89611af5565b604052918252848201925083810185019189831115611ba757600080fd5b938501935b82851015611bc557843584529385019392850192611bac565b8096505050505050509250929050565b600060208284031215611be757600080fd5b5035919050565b60008060208385031215611c0157600080fd5b823567ffffffffffffffff80821115611c1957600080fd5b818501915085601f830112611c2d57600080fd5b813581811115611c3c57600080fd5b8660208260051b8501011115611c5157600080fd5b60209290920196919550909350505050565b600060208284031215611c7557600080fd5b813563ffffffff81168114610e8857600080fd5b600080600060608486031215611c9e57600080fd5b505081359360208301359350604090920135919050565b80358015158114611ad557600080fd5b600060208284031215611cd757600080fd5b610e8882611cb5565b60008060408385031215611cf357600080fd5b611cfc83611abe565b946020939093013593505050565b600080600060608486031215611d1f57600080fd5b611d2884611abe565b9250611d3660208501611cb5565b9150604084013590509250925092565b600082611d5557611d55611a81565b500690565b600060018201611d6c57611d6c611a3b565b5060010190565b600060208284031215611d8557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60006020808352835160208401526020840151604084015261ffff6040850151166060840152606084015163ffffffff80821660808601528060808701511660a0860152505060a084015160c08085015280518060e086015260005b81811015611e1b5782810184015186820161010001528301611dfe565b506101009250600083828701015282601f19601f830116860101935050505092915050565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220f8b90f5a429cacb31b66df0b4a90b55dbee939ba9941b4d0aab5b499013d5a7364736f6c6343000818003300000000000000000000000000000000000000000000000000038d7ea4c68000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000001e1338000000000000000000000000063551da9c84e3654963f7d30ef994d8f44f36add0000000000000000000000002ced5bc349d9241a314d3739f12f5f6f2bda6a680000000000000000000000000000000000000000000000000000000000000320000000000000000000000000e2fe530c047f2d85298b07d9333c05737f1435fb0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000e9b4d32f829951a3ce145d2caa84cf66af56ca5e000000000000000000000000377e168af6a06075423aede50856de177efaac3e000000000000000000000000d7f86b4b8cae7d942340ff628f82735b7a20893a51a1158626539890bb46cbcf7a9387d1824cc3ac26a55841ab4f66bbc6c0628100000000000000000000000000000000000000000000000000000000674ef2c0000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000174876e8000000000000000000000000000000000000000000000000000000000000000032000000000000000000000000b039a8e618e05455d3b9606efe120d69428802b00000000000000000000000000472f681894067f270c68d00f982c59ef088ff0f0000000000000000000000000e30e1256a7729142ef4f29832bb11b60197326f00000000000000000000000018574e765c554c3b679c20c7f042ccfa3ae9bb540000000000000000000000004f4181ca564a45f86a933049fbb9c27118693137000000000000000000000000a967266d4ef3bc4c9e9d941ce0377e664831a5e8000000000000000000000000b16ac43d5be8e633679257c64faf7b39773ba55f000000000000000000000000bb42e428e5d967f2a02768333010564d8ed20435000000000000000000000000d93fb51820b71213fa63bfcf1862c7ea8e45f9f8000000000000000000000000da274009bee6d9d237cbf038e8591dcefca8f46a0000000000000000000000001eb2383dcdacc0f295f271a0cb9d773c8dfd7b6a0000000000000000000000004c15e560dbca6002398be258b483e36322f02cb900000000000000000000000002f771583231f8fe3f9cc20a22ea49f93ec39e9c0000000000000000000000000af91a93317fa34967769d7b3843808508eb2c210000000000000000000000000fcc3bc64e5dcee81337af2f6e78d63741f6b82400000000000000000000000014064be02e8084f471f8d5862c3ae7594bb624e700000000000000000000000014eb303905f9c8b96e0f29ae33c898da0d308b6c0000000000000000000000001c94dfef841aefbdd94f0f008510ed3e43c02fd800000000000000000000000020f68f6d733011c0c2305a6552e9ab7c417c0c4c00000000000000000000000030787facb68e5733169a6e2a92228e874001cd1b00000000000000000000000037ffcd57c153cc79e2d8b4d84dfc2d27e2112f4200000000000000000000000039f71db412bfa449b75043833e3dcc25c779fa9d00000000000000000000000039fe27637dcc68706c9344b96ef2ac6f22715fe90000000000000000000000004220ba8b1c1568a142edf0ff6df0e2d81d856a700000000000000000000000004f2daf3fba229755ada0768d3c5f62d76e4f0594000000000000000000000000557b6cc6a51cd86e3b2b0f4ee29af2ee5d62349200000000000000000000000056a1406b52293c386e43e6bd58c528816b48e90700000000000000000000000065e9b33973691e3ad488c9e9871c67c730ef036d00000000000000000000000068c80ba9fe526428b39b53b10268db487b30ba5f0000000000000000000000006a180038a4b5f1fe109d85b9c90250d8d141ec330000000000000000000000007083a39f5b8044d153ad705eb7dd78214c4b0110000000000000000000000000814a4dd09bcb79b345ae2dbcb03f8b6a8476f2f800000000000000000000000086c4040a603a701a332f8b4afa08053f0ea00f6c0000000000000000000000008d1ff41c8cf22154ad3754370bf43bd180b5bac80000000000000000000000009794281de32ce0edc1f7009628cf87698190a7810000000000000000000000009b04082ae277947290440f67b8309b2a009cd3c7000000000000000000000000b9d074afd94df661ab3df48668a6c6c22ac04b68000000000000000000000000c1d658b758106a483d0d888044849ee46f3e67b4000000000000000000000000c2aada445d2a9cbd9e7a0447cf44929ab3a7c081000000000000000000000000c989358dc22001e250d5fb4bdc5fd934f65354f6000000000000000000000000ca85ac2b88ddcabf8f5904de9dba2571abcbe36f000000000000000000000000d786c0b6ba4b2bc5039f1e2576205536d703bd99000000000000000000000000def11d13ad7c1b01581ae4cd0cb99c65c0b4f848000000000000000000000000e15376ff61951d73b78e0b14e011a5b1597c78f3000000000000000000000000e3f8555f003b9c7379221c44d7c31289ae626573000000000000000000000000e54ff2e30c1a8c2950b10d630e12a9e8676786ed000000000000000000000000f0c1198ff38d1ffe8416512a62c7cca7ee8fe157000000000000000000000000fdbb63c4c7ddaef07661a96d586388206eb5b4ec00000000000000000000000030b7caab584a551c10d3e703e4650c36cf623681000000000000000000000000fc9c9b5ff7bc03d2744506a4ac586f85797d847f

Deployed Bytecode

0x6080604052600436106104355760003560e01c80638da5cb5b11610229578063cde516271161012e578063ebdfd722116100b6578063f8ce58941161007a578063f8ce589414610d95578063f8f9892814610db5578063f954662114610dd5578063f9f4bfdd14610deb578063f9f94e3414610e0b57600080fd5b8063ebdfd72214610d13578063ec3a1d4b14610d29578063f2fde38b14610d3f578063f66a79a014610d5f578063f8b45b0514610d7f57600080fd5b8063e0f3ccf5116100fd578063e0f3ccf514610c7a578063e2f4560514610ca1578063e4748b9e14610cb7578063e7fa67e514610cde578063ea8a1af014610cfe57600080fd5b8063cde5162714610bc0578063d9cc0f3e14610be0578063dd62ed3e14610c00578063de35eb2414610c4657600080fd5b8063a9278a99116101b1578063c275c23111610180578063c275c23114610b26578063c408050614610b46578063c49b9a8014610b66578063caee544014610b86578063cb29813c14610ba057600080fd5b8063a9278a9914610a81578063bb44f3ac14610aa1578063bee0d6ad14610ac1578063bf56b37114610b1057600080fd5b80639a82a09a116101f85780639a82a09a146109bd5780639ff77da4146109e0578063a771654514610a0d578063a8aa1b3114610a2d578063a9059cbb14610a6157600080fd5b80638da5cb5b146109545780638ebfc7961461097257806395d89b411461099257806396792669146109a757600080fd5b806342966c681161033a5780636ddd1713116102c2578063838420131161028657806383842013146108bb57806383ebc78d146108dd578063857d81c9146108f357806388cda87314610913578063893fea8b1461093457600080fd5b80636ddd17131461083757806370a0823114610851578063715018a614610871578063719ce73e146108865780638183b3c8146108a657600080fd5b80635302750111610309578063530275011461077c57806354fd4d501461079b5780636101f1f8146107af5780636402511e146107e357806367dd01791461080357600080fd5b806342966c68146107035780634a829e79146107235780634b78286a14610742578063524513d61461076257600080fd5b806324dcfb37116103bd578063313ce5671161038c578063313ce5671461065757806332a8db871461067957806334303bcd1461068f5780633675f29b146106af5780633c191403146106e357600080fd5b806324dcfb37146105ec5780632b112e491461060c5780632ed6a367146106215780632ffe729a1461064157600080fd5b80631694505e116104045780631694505e146104c65780631732cded1461051257806318160ddd146105365780631959a0021461054b57806323b872dd146105cc57600080fd5b80630124043a1461044157806301339c211461046357806306fdde031461046b578063095ea7b31461049657600080fd5b3661043c57005b600080fd5b34801561044d57600080fd5b5061046161045c36600461342c565b610e2b565b005b610461610ed4565b34801561047757600080fd5b50610480611316565b60405161048d9190613465565b60405180910390f35b3480156104a257600080fd5b506104b66104b13660046134b4565b6113a8565b604051901515815260200161048d565b3480156104d257600080fd5b506104fa7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81565b6040516001600160a01b03909116815260200161048d565b34801561051e57600080fd5b50610528600d5481565b60405190815260200161048d565b34801561054257600080fd5b50600254610528565b34801561055757600080fd5b5061059e6105663660046134e0565b60276020526000908152604090208054600182015460029092015460ff80831693610100938490048216939092808316929190041685565b604080519515158652931515602086015292840191909152151560608301521515608082015260a00161048d565b3480156105d857600080fd5b506104b66105e7366004613504565b6113c2565b3480156105f857600080fd5b50610461610607366004613545565b6113e6565b34801561061857600080fd5b50610528611450565b34801561062d57600080fd5b5061046161063c36600461355e565b61146f565b34801561064d57600080fd5b50610528600b5481565b34801561066357600080fd5b5060095b60405160ff909116815260200161048d565b34801561068557600080fd5b5061052860225481565b34801561069b57600080fd5b506104616106aa3660046135d3565b6114df565b3480156106bb57600080fd5b506104fa7f000000000000000000000000e2fe530c047f2d85298b07d9333c05737f1435fb81565b3480156106ef57600080fd5b506104616106fe3660046135f9565b61151d565b34801561070f57600080fd5b5061046161071e366004613545565b611596565b34801561072f57600080fd5b50600c546104b690610100900460ff1681565b34801561074e57600080fd5b5061046161075d3660046134e0565b61168b565b34801561076e57600080fd5b506025546104b69060ff1681565b34801561078857600080fd5b506025546104b690610100900460ff1681565b3480156107a757600080fd5b506001610667565b3480156107bb57600080fd5b506104fa7f000000000000000000000000e9b4d32f829951a3ce145d2caa84cf66af56ca5e81565b3480156107ef57600080fd5b506104616107fe366004613545565b6116b5565b34801561080f57600080fd5b506104fa7f000000000000000000000000377e168af6a06075423aede50856de177efaac3e81565b34801561084357600080fd5b50600e546104b69060ff1681565b34801561085d57600080fd5b5061052861086c3660046134e0565b6116c2565b34801561087d57600080fd5b506104616116dd565b34801561089257600080fd5b506006546104fa906001600160a01b031681565b3480156108b257600080fd5b506104616116f1565b3480156108c757600080fd5b506025546104b690640100000000900460ff1681565b3480156108e957600080fd5b5061052860215481565b3480156108ff57600080fd5b5061046161090e366004613625565b611719565b34801561091f57600080fd5b506025546104b6906301000000900460ff1681565b34801561094057600080fd5b506008546104fa906001600160a01b031681565b34801561096057600080fd5b506005546001600160a01b03166104fa565b34801561097e57600080fd5b5061046161098d36600461342c565b611753565b34801561099e57600080fd5b50610480611786565b3480156109b357600080fd5b5061052860115481565b3480156109c957600080fd5b506025546104b69065010000000000900460ff1681565b3480156109ec57600080fd5b506105286109fb366004613545565b60106020526000908152604090205481565b348015610a1957600080fd5b50610461610a28366004613658565b611795565b348015610a3957600080fd5b506104fa7f000000000000000000000000c35153bf76cbf46c7664347a54ce5f3e02970f9e81565b348015610a6d57600080fd5b506104b6610a7c3660046134b4565b611867565b348015610a8d57600080fd5b50610461610a9c366004613545565b611875565b348015610aad57600080fd5b50610461610abc366004613545565b6118ae565b348015610acd57600080fd5b50601254601354601454601554601654610ae8949392919085565b604080519586526020860194909452928401919091526060830152608082015260a00161048d565b348015610b1c57600080fd5b5061052860095481565b348015610b3257600080fd5b50610461610b41366004613625565b6118bb565b348015610b5257600080fd5b50610461610b61366004613658565b6118d6565b348015610b7257600080fd5b50610461610b81366004613625565b611908565b348015610b9257600080fd5b50600c546104b69060ff1681565b348015610bac57600080fd5b50610461610bbb36600461371d565b611957565b348015610bcc57600080fd5b50610461610bdb366004613545565b611a4e565b348015610bec57600080fd5b50610461610bfb366004613545565b611a87565b348015610c0c57600080fd5b50610528610c1b366004613760565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b348015610c5257600080fd5b506105287f0000000000000000000000000000000000000000000000000000000001e1338081565b348015610c8657600080fd5b50601c54601d54601e54601f54602054610ae8949392919085565b348015610cad57600080fd5b50610528600f5481565b348015610cc357600080fd5b50601754601854601954601a54601b54610ae8949392919085565b348015610cea57600080fd5b50610461610cf9366004613545565b611ac0565b348015610d0a57600080fd5b50610461611af9565b348015610d1f57600080fd5b5061052860245481565b348015610d3557600080fd5b5061052860235481565b348015610d4b57600080fd5b50610461610d5a3660046134e0565b611ba5565b348015610d6b57600080fd5b506007546104fa906001600160a01b031681565b348015610d8b57600080fd5b50610528600a5481565b348015610da157600080fd5b50610461610db03660046134e0565b611be5565b348015610dc157600080fd5b50610461610dd0366004613658565b611caf565b348015610de157600080fd5b5061052860265481565b348015610df757600080fd5b506025546104b69062010000900460ff1681565b348015610e1757600080fd5b50610461610e263660046134e0565b611d16565b610e33611d50565b6001600160a01b038281166000908152602760205260409020600201805460ff19168315151790556006541663fd8703608383610e6f826116c2565b6040516001600160e01b031960e086901b1681526001600160a01b03909316600484015290151560248301526044820152606401600060405180830381600087803b158015610ebd57600080fd5b505af1925050508015610ece575060015b505b5050565b610edc611d50565b6002600d55600954151580610efc575060255465010000000000900460ff165b15610f1a5760405163c52a9bd360e01b815260040160405180910390fd5b426009819055602354610f2c916137a4565b6024556025805460ff19166001179055610f69307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d600019611d7d565b610f85610f75306116c2565b610f7f34476137b7565b30611d8a565b50600854604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018187875af1158015610fd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff591906137ca565b6110009060016137a4565b905060015b818110156110bd576008546040516331a9108f60e11b8152600481018390526001916027916000916001600160a01b031690636352211e906024016020604051808303816000875af115801561105f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108391906137e3565b6001600160a01b03168152602081019190915260400160002060020180549115156101000261ff0019909216919091179055600101611005565b506040516370a0823160e01b81523060048201526000907f000000000000000000000000c35153bf76cbf46c7664347a54ce5f3e02970f9e6001600160a01b0316906370a0823190602401602060405180830381865afa158015611125573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114991906137ca565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000e2fe530c047f2d85298b07d9333c05737f1435fb81166004830152602482018390529192507f000000000000000000000000c35153bf76cbf46c7664347a54ce5f3e02970f9e9091169063095ea7b3906044016020604051808303816000875af11580156111dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112019190613800565b506001600160a01b037f000000000000000000000000e2fe530c047f2d85298b07d9333c05737f1435fb16635af06fed347f000000000000000000000000c35153bf76cbf46c7664347a54ce5f3e02970f9e338561127f7f0000000000000000000000000000000000000000000000000000000001e13380426137a4565b6040516001600160e01b031960e088901b1681526001600160a01b0394851660048201529390921660248401526044830152606482015260006084820181905260a482015260c40160206040518083038185885af11580156112e5573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061130a91906137ca565b60265550506001600d55565b6060600380546113259061381d565b80601f01602080910402602001604051908101604052809291908181526020018280546113519061381d565b801561139e5780601f106113735761010080835404028352916020019161139e565b820191906000526020600020905b81548152906001019060200180831161138157829003601f168201915b5050505050905090565b6000336113b6818585611d7d565b60019150505b92915050565b6000336113d0858285611e4b565b6113db858585611ec9565b506001949350505050565b6113ee611d50565b6006546040516324dcfb3760e01b8152600481018390526001600160a01b03909116906324dcfb37906024015b600060405180830381600087803b15801561143557600080fd5b505af1158015611449573d6000803e3d6000fd5b5050505050565b600061145d61dead6116c2565b60025461146a91906137b7565b905090565b611477611d50565b600654604051632ed6a36760e01b81526001600160a01b0390911690632ed6a367906114a99085908590600401613857565b600060405180830381600087803b1580156114c357600080fd5b505af11580156114d7573d6000803e3d6000fd5b505050505050565b6114e7611d50565b6006546040516334303bcd60e01b815263ffffffff831660048201526001600160a01b03909116906334303bcd9060240161141b565b611525611d50565b600654604051633c19140360e01b81526004810185905260248101849052604481018390526001600160a01b0390911690633c19140390606401600060405180830381600087803b15801561157957600080fd5b505af115801561158d573d6000803e3d6000fd5b50505050505050565b6115a03382611f28565b3360009081526027602052604090206002015460ff1661168857600654604051632770a7eb60e21b8152336004820152602481018390526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b15801561160657600080fd5b505af1925050508015611617575060015b506006546001600160a01b031663e30443bc33611633816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561167957600080fd5b505af1925050508015610ed057505b50565b611693611d50565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b6116bd611d50565b600f55565b6001600160a01b031660009081526020819052604090205490565b6116e5611d50565b6116ef6000611f5e565b565b6116f9611d50565b6116ef303360165461170a306116c2565b61171491906137b7565b611fb0565b611721611d50565b60065460405163857d81c960e01b815282151560048201526001600160a01b039091169063857d81c99060240161141b565b61175b611d50565b6001600160a01b03919091166000908152602760205260409020805460ff1916911515919091179055565b6060600480546113259061381d565b61179d611d50565b805160005b81811015610ece5760065483516001600160a01b039091169063fd870360908590849081106117d3576117d3613890565b602002602001015160016117ff8786815181106117f2576117f2613890565b60200260200101516116c2565b6040516001600160e01b031960e086901b1681526001600160a01b03909316600484015290151560248301526044820152606401600060405180830381600087803b15801561184d57600080fd5b505af192505050801561185e575060015b506001016117a2565b6000336113b6818585611ec9565b61187d611d50565b60065460405163a9278a9960e01b8152600481018390526001600160a01b039091169063a9278a999060240161141b565b6118b6611d50565b601155565b6118c3611d50565b600c805460ff1916911515919091179055565b6118de611d50565b600954156118ff5760405163c52a9bd360e01b815260040160405180910390fd5b611688816120f1565b611910611d50565b600e805460ff19168215159081179091556040519081527f53726dfcaf90650aa7eb35524f4d3220f07413c8d6cb404cc8c18bf5591bc1599060200160405180910390a150565b61195f611d50565b602554610100900460ff16158061197f575060255462010000900460ff16155b1561199d5760405163c52a9bd360e01b815260040160405180910390fd5b6119a56133ca565b60408101879052858152602081018590526119be6133ca565b60408101859052838152602081018390526009546000036119e1576002806119e9565b6119e961215a565b6060838101919091528301526119ff82826121cc565b8151601755602080830151601855604080840151601955606080850151601a55608094850151601b558351601c5583830151601d5590830151601e55820151601f559101519055505050505050565b611a56611d50565b60065460405163cde5162760e01b8152600481018390526001600160a01b039091169063cde516279060240161141b565b611a8f611d50565b600654604051636ce6079f60e11b8152600481018390526001600160a01b039091169063d9cc0f3e9060240161141b565b611ac8611d50565b60065460405163e7fa67e560e01b8152600481018390526001600160a01b039091169063e7fa67e59060240161141b565b611b01611d50565b60095415611b225760405163c52a9bd360e01b815260040160405180910390fd5b6025805465ff0000000000191665010000000000179055611b5830611b4f6005546001600160a01b031690565b611714306116c2565b6005546040516001600160a01b03909116904790600081818185875af1925050503d8060008114610ece576040519150601f19603f3d011682016040523d82523d6000602084013e505050565b611bad611d50565b6001600160a01b038116611bdc57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61168881611f5e565b611bed611d50565b6006546001600160a01b0390811690821603611c0857600080fd5b6000819050306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7991906137e3565b6001600160a01b031614611c8c57600080fd5b600680546001600160a01b0319166001600160a01b039290921691909117905550565b611cb7611d50565b805160005b81811015610ece57600160276000858481518110611cdc57611cdc613890565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101611cbc565b611d1e611d50565b600654604051633e7e538d60e21b81526001600160a01b0383811660048301529091169063f9f94e349060240161141b565b6005546001600160a01b031633146116ef5760405163118cdaa760e01b8152336004820152602401611bd3565b610ece83838360016122a9565b60405163f305d71960e01b815230600482015260248101849052600060448201819052606482018190526001600160a01b0383811660848401524260a4840152909182917f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d169063f305d71990869060c40160606040518083038185885af1158015611e1a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e3f91906138a6565b50909695505050505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114611ec35781811015611eb457604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401611bd3565b611ec3848484840360006122a9565b50505050565b6001600160a01b038316611ef357604051634b637e8f60e11b815260006004820152602401611bd3565b6001600160a01b038216611f1d5760405163ec442f0560e01b815260006004820152602401611bd3565b610ece83838361237e565b6001600160a01b038216611f5257604051634b637e8f60e11b815260006004820152602401611bd3565b610ed08260008361237e565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611fbb838383612b8b565b6001600160a01b03831660009081526027602052604090206002015460ff16612052576006546001600160a01b031663e30443bc84611ff9816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561203f57600080fd5b505af1925050508015612050575060015b505b6001600160a01b03821660009081526027602052604090206002015460ff16610ece576006546001600160a01b031663e30443bc83612090816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156120d657600080fd5b505af19250505080156120e7575060015b15610ece57505050565b805160005b81811015610ece5760016027600085848151811061211657612116613890565b6020908102919091018101516001600160a01b0316825281019190915260400160002060020180549115156101000261ff00199092169190911790556001016120f6565b60008060006009544261216d91906137b7565b90506228de808111156121995750506025805464ff000000001916640100000000179055506000908190565b620151808111156121c15750506025805463ff00000019166301000000179055506001908190565b506002928392509050565b6020820151825160408401516121e291906137a4565b6121ec91906137a4565b608083018190526000036122065760006060830152612220565b81606001518260800181815161221c91906137a4565b9052505b60208101518151604083015161223691906137a4565b61224091906137a4565b6080820181905260000361225a5760006060820152612274565b80606001518160800181815161227091906137a4565b9052505b60078260800151118061228b575060078160800151115b15610ed05760405163c52a9bd360e01b815260040160405180910390fd5b6001600160a01b0384166122d35760405163e602df0560e01b815260006004820152602401611bd3565b6001600160a01b0383166122fd57604051634a1406b160e11b815260006004820152602401611bd3565b6001600160a01b0380851660009081526001602090815260408083209387168352929052208290558015611ec357826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161237091815260200190565b60405180910390a350505050565b600d546002148061239c57506005546001600160a01b038481169116145b806123b457506005546001600160a01b038381169116145b806123c757506001600160a01b03831630145b806123da57506001600160a01b03821630145b806123e3575080155b156123f357610ece838383611fb0565b600954600003612416576040516312f1f92360e01b815260040160405180910390fd5b6001600160a01b038084166000908152602760205260408082209285168252902060255460ff161561249d57602454421015612492576002820154610100900460ff16158061246f57506002810154610100900460ff16155b1561248d57604051630b094f2760e31b815260040160405180910390fd5b61249d565b6025805460ff191690555b600c54610100900460ff1661253c576000600954426124bc91906137b7565b905060006124cb6078836138d4565b6124d69060646138f6565b600b546124e391906137a4565b90506103b68111156125035750600c805461ff0019166101001790556103e85b6000620186a08261251360025490565b61251d91906138f6565b61252791906138d4565b9050600a54811461253857600a8190555b5050505b600c5460ff161561258f578054610100900460ff161580156125715750600a54612565856116c2565b61256f90856137a4565b115b1561258f5760405163fd42866160e01b815260040160405180910390fd5b601654600f54811080159081906125a85750600e5460ff165b80156125e657507f000000000000000000000000c35153bf76cbf46c7664347a54ce5f3e02970f9e6001600160a01b0316876001600160a01b031614155b8015612602575060115443600090815260106020526040902054105b156126365743600090815260106020526040812080549091906126249061390d565b90915550600f54612636908390612cb5565b835460ff1615801561264a5750825460ff16155b15612a7457602554601790601c90640100000000900460ff166129515760006009544261267791906137b7565b6025549091506301000000900460ff1615801561269657506201518081115b15612749576000836003015484600401546126b191906137b7565b9050806000036126ce5760006004850181905560038501556126e5565b83546126db9060016137a4565b8455600160038501555b6000836003015484600401546126fb91906137b7565b90508060000361271857600060048501819055600385015561272f565b83546127259060016137a4565b8455600160038501555b50506025805463ff0000001916630100000017905561294f565b6228de808111156127b457826003015483600001600082825461276c91906137a4565b90915550506003820154825483906000906127889084906137a4565b9091555050600060038085018290558301556025805464ff00000000191664010000000017905561294f565b602554610100900460ff1661288057602154806107098310156127ea576127dc6078846138d4565b6127e790600f6137b7565b90505b81811161283b576004850182905560038501548554600287015461280e90856137b7565b61281891906137b7565b61282291906137b7565b60018601556025805461ff00191661010017905561287d565b8460040154811461287d576004850181905560038501548554600287015461286390846137b7565b61286d91906137b7565b61287791906137b7565b60018601555b50505b60255462010000900460ff1661294f57602254806109618310156128b7576128a96078846138d4565b6128b49060146137b7565b90505b81811161290a57600484018290556003840154845460028601546128db90856137b7565b6128e591906137b7565b6128ef91906137b7565b60018501556025805462ff000019166201000017905561294c565b8360040154811461294c576004840181905560038401548454600286015461293290846137b7565b61293c91906137b7565b61294691906137b7565b60018501555b50505b505b60007f000000000000000000000000c35153bf76cbf46c7664347a54ce5f3e02970f9e6001600160a01b0316896001600160a01b0316036129d5576040805160a081018252835481526001840154602082015260028401549181019190915260038301546060820152600483015460808201526129ce9089613108565b9050612a53565b7f000000000000000000000000c35153bf76cbf46c7664347a54ce5f3e02970f9e6001600160a01b03168a6001600160a01b031603612a53576040805160a08101825284548152600185015460208201526002850154918101919091526003840154606082015260048401546080820152612a509089613108565b90505b8015612a7057612a6381896137b7565b9750612a708a3083612b8b565b5050505b612a7f878787612b8b565b600284015460ff16612aff576006546001600160a01b031663e30443bc88612aa6816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015612aec57600080fd5b505af1925050508015612afd575060015b505b600283015460ff1661158d576006546001600160a01b031663e30443bc87612b26816116c2565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015612b6c57600080fd5b505af1925050508015612b7d575060015b1561158d5750505050505050565b6001600160a01b038316612bb6578060026000828254612bab91906137a4565b90915550612c289050565b6001600160a01b03831660009081526020819052604090205481811015612c095760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401611bd3565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b038216612c4457600280548290039055612c63565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612ca891815260200190565b60405180910390a3505050565b6002600d556012612cc46133ca565b81548490612cd290856138f6565b612cdc91906138d4565b815260018201548490612cef90856138f6565b612cf991906138d4565b602082015260028201548490612d0f90856138f6565b612d1991906138d4565b604082015260038201548490612d2f90856138f6565b612d3991906138d4565b60608201526040810151600090612d52906002906138d4565b9050612d5e81856137b7565b60808301819052600090612d719061322f565b9050612d7b6133ca565b60808401518451612d8c90846138f6565b612d9691906138d4565b80825215612df45760065481516040516001600160a01b0390921691600081818185875af1925050503d8060008114612deb576040519150601f19603f3d011682016040523d82523d6000602084013e612df0565b606091505b5050505b60808401516020850151612e0890846138f6565b612e1291906138d4565b6020820181905215612e775760075460208201516040516001600160a01b0390921691600081818185875af1925050503d8060008114612e6e576040519150601f19603f3d011682016040523d82523d6000602084013e612e73565b606091505b5050505b60808401516060850151612e8b90846138f6565b612e9591906138d4565b6060820181905215612fa957600060028260600151612eb491906138d4565b90507f000000000000000000000000377e168af6a06075423aede50856de177efaac3e6001600160a01b03168160405160006040518083038185875af1925050503d8060008114612f21576040519150601f19603f3d011682016040523d82523d6000602084013e612f26565b606091505b5050507f000000000000000000000000e9b4d32f829951a3ce145d2caa84cf66af56ca5e6001600160a01b0316818360600151612f6391906137b7565b604051600081818185875af1925050503d8060008114612f9f576040519150601f19603f3d011682016040523d82523d6000602084013e612fa4565b606091505b505050505b47604082015260008315801590612fc4575060008260400151115b1561302357612fda84836040015161dead611d8a565b90507f28fc98272ce761178794ad6768050fea1648e07f1e2ffe15afd3a290f838148684836040015160405161301a929190918252602082015260400190565b60405180910390a15b600061302f82866137b7565b866040015161303e91906137b7565b9050856000015187600001600082825461305891906137b7565b909155505060208601516001880180546000906130769084906137b7565b925050819055508087600201600082825461309191906137b7565b909155505060608601516003880180546000906130af9084906137b7565b90915550506060860151602087015187518392916130cc916137a4565b6130d691906137a4565b6130e091906137a4565b8760040160008282546130f391906137b7565b90915550506001600d55505050505050505050565b600082608001516000146113bc57606483608001518361312891906138f6565b61313291906138d4565b6080840151845191925060129161314990846138f6565b61315391906138d4565b81600001600082825461316691906137a4565b90915550506080840151602085015161317f90846138f6565b61318991906138d4565b81600101600082825461319c91906137a4565b9091555050608084015160408501516131b590846138f6565b6131bf91906138d4565b8160020160008282546131d291906137a4565b9091555050608084015160608501516131eb90846138f6565b6131f591906138d4565b81600301600082825461320891906137a4565b925050819055508181600401600082825461322391906137a4565b90915550505092915050565b604080516002808252606082018352600092479284929091602083019080368337019050509050308160008151811061326a5761326a613890565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330c91906137e3565b8160018151811061331f5761331f613890565b6001600160a01b03928316602091820292909201015260405163791ac94760e01b81527f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d9091169063791ac94790613384908790600090869030904290600401613926565b600060405180830381600087803b15801561339e57600080fd5b505af11580156133b2573d6000803e3d6000fd5b5050505081476133c291906137b7565b949350505050565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b038116811461168857600080fd5b8035613419816133f9565b919050565b801515811461168857600080fd5b6000806040838503121561343f57600080fd5b823561344a816133f9565b9150602083013561345a8161341e565b809150509250929050565b60006020808352835180602085015260005b8181101561349357858101830151858201604001528201613477565b506000604082860101526040601f19601f8301168501019250505092915050565b600080604083850312156134c757600080fd5b82356134d2816133f9565b946020939093013593505050565b6000602082840312156134f257600080fd5b81356134fd816133f9565b9392505050565b60008060006060848603121561351957600080fd5b8335613524816133f9565b92506020840135613534816133f9565b929592945050506040919091013590565b60006020828403121561355757600080fd5b5035919050565b6000806020838503121561357157600080fd5b823567ffffffffffffffff8082111561358957600080fd5b818501915085601f83011261359d57600080fd5b8135818111156135ac57600080fd5b8660208260051b85010111156135c157600080fd5b60209290920196919550909350505050565b6000602082840312156135e557600080fd5b813563ffffffff811681146134fd57600080fd5b60008060006060848603121561360e57600080fd5b505081359360208301359350604090920135919050565b60006020828403121561363757600080fd5b81356134fd8161341e565b634e487b7160e01b600052604160045260246000fd5b6000602080838503121561366b57600080fd5b823567ffffffffffffffff8082111561368357600080fd5b818501915085601f83011261369757600080fd5b8135818111156136a9576136a9613642565b8060051b604051601f19603f830116810181811085821117156136ce576136ce613642565b6040529182528482019250838101850191888311156136ec57600080fd5b938501935b82851015613711576137028561340e565b845293850193928501926136f1565b98975050505050505050565b60008060008060008060c0878903121561373657600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b6000806040838503121561377357600080fd5b823561377e816133f9565b9150602083013561345a816133f9565b634e487b7160e01b600052601160045260246000fd5b808201808211156113bc576113bc61378e565b818103818111156113bc576113bc61378e565b6000602082840312156137dc57600080fd5b5051919050565b6000602082840312156137f557600080fd5b81516134fd816133f9565b60006020828403121561381257600080fd5b81516134fd8161341e565b600181811c9082168061383157607f821691505b60208210810361385157634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252810182905260006001600160fb1b0383111561387757600080fd5b8260051b80856040850137919091016040019392505050565b634e487b7160e01b600052603260045260246000fd5b6000806000606084860312156138bb57600080fd5b8351925060208401519150604084015190509250925092565b6000826138f157634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176113bc576113bc61378e565b60006001820161391f5761391f61378e565b5060010190565b600060a08201878352602087602085015260a0604085015281875180845260c08601915060208901935060005b818110156139785784516001600160a01b031683529383019391830191600101613953565b50506001600160a01b0396909616606085015250505060800152939250505056fea264697066735822122002c2c1ccb3925245c3b4ebd15cb3bf4cf80c78612ea7c61b5d65022b02a8b7b464736f6c63430008180033

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

00000000000000000000000000000000000000000000000000038d7ea4c68000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000001e1338000000000000000000000000063551da9c84e3654963f7d30ef994d8f44f36add0000000000000000000000002ced5bc349d9241a314d3739f12f5f6f2bda6a680000000000000000000000000000000000000000000000000000000000000320000000000000000000000000e2fe530c047f2d85298b07d9333c05737f1435fb0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000e9b4d32f829951a3ce145d2caa84cf66af56ca5e000000000000000000000000377e168af6a06075423aede50856de177efaac3e000000000000000000000000d7f86b4b8cae7d942340ff628f82735b7a20893a51a1158626539890bb46cbcf7a9387d1824cc3ac26a55841ab4f66bbc6c0628100000000000000000000000000000000000000000000000000000000674ef2c0000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000174876e8000000000000000000000000000000000000000000000000000000000000000032000000000000000000000000b039a8e618e05455d3b9606efe120d69428802b00000000000000000000000000472f681894067f270c68d00f982c59ef088ff0f0000000000000000000000000e30e1256a7729142ef4f29832bb11b60197326f00000000000000000000000018574e765c554c3b679c20c7f042ccfa3ae9bb540000000000000000000000004f4181ca564a45f86a933049fbb9c27118693137000000000000000000000000a967266d4ef3bc4c9e9d941ce0377e664831a5e8000000000000000000000000b16ac43d5be8e633679257c64faf7b39773ba55f000000000000000000000000bb42e428e5d967f2a02768333010564d8ed20435000000000000000000000000d93fb51820b71213fa63bfcf1862c7ea8e45f9f8000000000000000000000000da274009bee6d9d237cbf038e8591dcefca8f46a0000000000000000000000001eb2383dcdacc0f295f271a0cb9d773c8dfd7b6a0000000000000000000000004c15e560dbca6002398be258b483e36322f02cb900000000000000000000000002f771583231f8fe3f9cc20a22ea49f93ec39e9c0000000000000000000000000af91a93317fa34967769d7b3843808508eb2c210000000000000000000000000fcc3bc64e5dcee81337af2f6e78d63741f6b82400000000000000000000000014064be02e8084f471f8d5862c3ae7594bb624e700000000000000000000000014eb303905f9c8b96e0f29ae33c898da0d308b6c0000000000000000000000001c94dfef841aefbdd94f0f008510ed3e43c02fd800000000000000000000000020f68f6d733011c0c2305a6552e9ab7c417c0c4c00000000000000000000000030787facb68e5733169a6e2a92228e874001cd1b00000000000000000000000037ffcd57c153cc79e2d8b4d84dfc2d27e2112f4200000000000000000000000039f71db412bfa449b75043833e3dcc25c779fa9d00000000000000000000000039fe27637dcc68706c9344b96ef2ac6f22715fe90000000000000000000000004220ba8b1c1568a142edf0ff6df0e2d81d856a700000000000000000000000004f2daf3fba229755ada0768d3c5f62d76e4f0594000000000000000000000000557b6cc6a51cd86e3b2b0f4ee29af2ee5d62349200000000000000000000000056a1406b52293c386e43e6bd58c528816b48e90700000000000000000000000065e9b33973691e3ad488c9e9871c67c730ef036d00000000000000000000000068c80ba9fe526428b39b53b10268db487b30ba5f0000000000000000000000006a180038a4b5f1fe109d85b9c90250d8d141ec330000000000000000000000007083a39f5b8044d153ad705eb7dd78214c4b0110000000000000000000000000814a4dd09bcb79b345ae2dbcb03f8b6a8476f2f800000000000000000000000086c4040a603a701a332f8b4afa08053f0ea00f6c0000000000000000000000008d1ff41c8cf22154ad3754370bf43bd180b5bac80000000000000000000000009794281de32ce0edc1f7009628cf87698190a7810000000000000000000000009b04082ae277947290440f67b8309b2a009cd3c7000000000000000000000000b9d074afd94df661ab3df48668a6c6c22ac04b68000000000000000000000000c1d658b758106a483d0d888044849ee46f3e67b4000000000000000000000000c2aada445d2a9cbd9e7a0447cf44929ab3a7c081000000000000000000000000c989358dc22001e250d5fb4bdc5fd934f65354f6000000000000000000000000ca85ac2b88ddcabf8f5904de9dba2571abcbe36f000000000000000000000000d786c0b6ba4b2bc5039f1e2576205536d703bd99000000000000000000000000def11d13ad7c1b01581ae4cd0cb99c65c0b4f848000000000000000000000000e15376ff61951d73b78e0b14e011a5b1597c78f3000000000000000000000000e3f8555f003b9c7379221c44d7c31289ae626573000000000000000000000000e54ff2e30c1a8c2950b10d630e12a9e8676786ed000000000000000000000000f0c1198ff38d1ffe8416512a62c7cca7ee8fe157000000000000000000000000fdbb63c4c7ddaef07661a96d586388206eb5b4ec00000000000000000000000030b7caab584a551c10d3e703e4650c36cf623681000000000000000000000000fc9c9b5ff7bc03d2744506a4ac586f85797d847f

-----Decoded View---------------
Arg [0] : _totalSupply (uint256): 1000000000000000
Arg [1] : _buyFees (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [2] : _sellFees (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [3] : _percentToLP (uint256): 80
Arg [4] : _lpLockDuration (uint256): 31536000
Arg [5] : _secondaryWallet (address): 0x63551DA9c84e3654963F7D30ef994D8f44f36aDd
Arg [6] : _proofPassNFT (address): 0x2cED5bc349D9241a314d3739f12f5f6f2BDA6A68
Arg [7] : _whitelist (address[]): 0xB039A8e618E05455D3b9606Efe120d69428802b0,0x0472f681894067f270c68d00F982C59eF088ff0F,0x0e30e1256a7729142Ef4F29832Bb11b60197326f,0x18574E765C554C3B679C20C7f042CCFA3AE9BB54,0x4f4181ca564A45F86A933049fbB9c27118693137,0xa967266d4Ef3bc4c9E9D941CE0377e664831A5E8,0xB16Ac43d5Be8E633679257C64FaF7B39773BA55f,0xBB42e428e5D967f2A02768333010564d8ed20435,0xD93Fb51820B71213FA63BFcf1862c7eA8e45f9f8,0xDA274009BEe6d9D237cBF038E8591dceFCa8f46A,0x1Eb2383dcDAcc0F295F271a0cb9d773C8dFD7b6A,0x4C15e560dbcA6002398Be258B483E36322f02cb9,0x02F771583231f8Fe3f9CC20A22ea49f93Ec39E9C,0x0af91A93317Fa34967769d7b3843808508EB2C21,0x0fCc3Bc64e5dcEE81337AF2F6E78D63741F6b824,0x14064be02E8084f471f8D5862C3aE7594bb624E7,0x14EB303905f9c8B96e0f29ae33C898da0d308b6c,0x1C94dFeF841aefbDD94F0f008510Ed3E43C02fD8,0x20f68F6d733011C0C2305A6552E9Ab7c417C0c4C,0x30787faCB68e5733169A6e2A92228e874001cd1b,0x37ffcD57C153Cc79E2d8b4D84dFc2D27e2112F42,0x39F71DB412bfA449b75043833E3Dcc25C779fA9d,0x39Fe27637DCC68706c9344b96EF2aC6f22715fE9,0x4220Ba8b1c1568a142Edf0ff6df0E2D81D856A70,0x4F2dAf3fBa229755ADA0768D3c5F62d76e4f0594,0x557b6Cc6A51CD86e3b2B0F4ee29AF2eE5D623492,0x56a1406B52293c386E43e6bD58C528816B48E907,0x65e9B33973691e3aD488C9e9871c67C730EF036d,0x68c80Ba9FE526428b39b53B10268dB487b30BA5f,0x6a180038a4b5F1fE109D85b9C90250d8D141EC33,0x7083a39f5b8044d153ad705Eb7dd78214c4b0110,0x814A4dd09bCB79b345AE2DbcB03F8B6a8476F2F8,0x86c4040a603a701A332f8B4Afa08053F0EA00F6c,0x8D1fF41C8cf22154aD3754370BF43bD180b5BaC8,0x9794281De32cE0Edc1F7009628CF87698190A781,0x9B04082AE277947290440F67B8309B2A009cD3c7,0xB9d074afD94df661AB3Df48668A6C6c22aC04B68,0xC1d658B758106a483D0D888044849Ee46f3e67b4,0xC2AadA445d2a9CbD9e7A0447Cf44929Ab3A7c081,0xc989358DC22001E250D5fb4bdC5FD934F65354F6,0xCA85AC2b88ddcabf8f5904de9DBa2571abCBE36F,0xD786c0B6bA4b2Bc5039f1E2576205536D703BD99,0xDeF11d13aD7c1b01581aE4Cd0Cb99c65C0B4F848,0xE15376fF61951D73B78e0B14E011A5B1597c78f3,0xe3f8555f003B9c7379221C44D7C31289ae626573,0xe54fF2e30c1A8c2950B10D630E12A9E8676786eD,0xF0c1198FF38D1fFE8416512a62C7CcA7Ee8FE157,0xfdbB63c4c7ddaef07661A96d586388206eb5b4EC,0x30B7CAab584A551C10d3e703E4650C36cf623681,0xfc9c9b5Ff7bc03D2744506A4Ac586F85797D847f
Arg [8] : _addresses (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [9] : prizePoolArgs (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
76 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000038d7ea4c68000
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000050
Arg [12] : 0000000000000000000000000000000000000000000000000000000001e13380
Arg [13] : 00000000000000000000000063551da9c84e3654963f7d30ef994d8f44f36add
Arg [14] : 0000000000000000000000002ced5bc349d9241a314d3739f12f5f6f2bda6a68
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000320
Arg [16] : 000000000000000000000000e2fe530c047f2d85298b07d9333c05737f1435fb
Arg [17] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [18] : 000000000000000000000000e9b4d32f829951a3ce145d2caa84cf66af56ca5e
Arg [19] : 000000000000000000000000377e168af6a06075423aede50856de177efaac3e
Arg [20] : 000000000000000000000000d7f86b4b8cae7d942340ff628f82735b7a20893a
Arg [21] : 51a1158626539890bb46cbcf7a9387d1824cc3ac26a55841ab4f66bbc6c06281
Arg [22] : 00000000000000000000000000000000000000000000000000000000674ef2c0
Arg [23] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [24] : 000000000000000000000000000000000000000000000000000000174876e800
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000032
Arg [26] : 000000000000000000000000b039a8e618e05455d3b9606efe120d69428802b0
Arg [27] : 0000000000000000000000000472f681894067f270c68d00f982c59ef088ff0f
Arg [28] : 0000000000000000000000000e30e1256a7729142ef4f29832bb11b60197326f
Arg [29] : 00000000000000000000000018574e765c554c3b679c20c7f042ccfa3ae9bb54
Arg [30] : 0000000000000000000000004f4181ca564a45f86a933049fbb9c27118693137
Arg [31] : 000000000000000000000000a967266d4ef3bc4c9e9d941ce0377e664831a5e8
Arg [32] : 000000000000000000000000b16ac43d5be8e633679257c64faf7b39773ba55f
Arg [33] : 000000000000000000000000bb42e428e5d967f2a02768333010564d8ed20435
Arg [34] : 000000000000000000000000d93fb51820b71213fa63bfcf1862c7ea8e45f9f8
Arg [35] : 000000000000000000000000da274009bee6d9d237cbf038e8591dcefca8f46a
Arg [36] : 0000000000000000000000001eb2383dcdacc0f295f271a0cb9d773c8dfd7b6a
Arg [37] : 0000000000000000000000004c15e560dbca6002398be258b483e36322f02cb9
Arg [38] : 00000000000000000000000002f771583231f8fe3f9cc20a22ea49f93ec39e9c
Arg [39] : 0000000000000000000000000af91a93317fa34967769d7b3843808508eb2c21
Arg [40] : 0000000000000000000000000fcc3bc64e5dcee81337af2f6e78d63741f6b824
Arg [41] : 00000000000000000000000014064be02e8084f471f8d5862c3ae7594bb624e7
Arg [42] : 00000000000000000000000014eb303905f9c8b96e0f29ae33c898da0d308b6c
Arg [43] : 0000000000000000000000001c94dfef841aefbdd94f0f008510ed3e43c02fd8
Arg [44] : 00000000000000000000000020f68f6d733011c0c2305a6552e9ab7c417c0c4c
Arg [45] : 00000000000000000000000030787facb68e5733169a6e2a92228e874001cd1b
Arg [46] : 00000000000000000000000037ffcd57c153cc79e2d8b4d84dfc2d27e2112f42
Arg [47] : 00000000000000000000000039f71db412bfa449b75043833e3dcc25c779fa9d
Arg [48] : 00000000000000000000000039fe27637dcc68706c9344b96ef2ac6f22715fe9
Arg [49] : 0000000000000000000000004220ba8b1c1568a142edf0ff6df0e2d81d856a70
Arg [50] : 0000000000000000000000004f2daf3fba229755ada0768d3c5f62d76e4f0594
Arg [51] : 000000000000000000000000557b6cc6a51cd86e3b2b0f4ee29af2ee5d623492
Arg [52] : 00000000000000000000000056a1406b52293c386e43e6bd58c528816b48e907
Arg [53] : 00000000000000000000000065e9b33973691e3ad488c9e9871c67c730ef036d
Arg [54] : 00000000000000000000000068c80ba9fe526428b39b53b10268db487b30ba5f
Arg [55] : 0000000000000000000000006a180038a4b5f1fe109d85b9c90250d8d141ec33
Arg [56] : 0000000000000000000000007083a39f5b8044d153ad705eb7dd78214c4b0110
Arg [57] : 000000000000000000000000814a4dd09bcb79b345ae2dbcb03f8b6a8476f2f8
Arg [58] : 00000000000000000000000086c4040a603a701a332f8b4afa08053f0ea00f6c
Arg [59] : 0000000000000000000000008d1ff41c8cf22154ad3754370bf43bd180b5bac8
Arg [60] : 0000000000000000000000009794281de32ce0edc1f7009628cf87698190a781
Arg [61] : 0000000000000000000000009b04082ae277947290440f67b8309b2a009cd3c7
Arg [62] : 000000000000000000000000b9d074afd94df661ab3df48668a6c6c22ac04b68
Arg [63] : 000000000000000000000000c1d658b758106a483d0d888044849ee46f3e67b4
Arg [64] : 000000000000000000000000c2aada445d2a9cbd9e7a0447cf44929ab3a7c081
Arg [65] : 000000000000000000000000c989358dc22001e250d5fb4bdc5fd934f65354f6
Arg [66] : 000000000000000000000000ca85ac2b88ddcabf8f5904de9dba2571abcbe36f
Arg [67] : 000000000000000000000000d786c0b6ba4b2bc5039f1e2576205536d703bd99
Arg [68] : 000000000000000000000000def11d13ad7c1b01581ae4cd0cb99c65c0b4f848
Arg [69] : 000000000000000000000000e15376ff61951d73b78e0b14e011a5b1597c78f3
Arg [70] : 000000000000000000000000e3f8555f003b9c7379221c44d7c31289ae626573
Arg [71] : 000000000000000000000000e54ff2e30c1a8c2950b10d630e12a9e8676786ed
Arg [72] : 000000000000000000000000f0c1198ff38d1ffe8416512a62c7cca7ee8fe157
Arg [73] : 000000000000000000000000fdbb63c4c7ddaef07661a96d586388206eb5b4ec
Arg [74] : 00000000000000000000000030b7caab584a551c10d3e703e4650c36cf623681
Arg [75] : 000000000000000000000000fc9c9b5ff7bc03d2744506a4ac586f85797d847f


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.