ETH Price: $2,488.15 (+2.00%)

Token

Anonymous VC (ANON)
 

Overview

Max Total Supply

1,000,000,000 ANON

Holders

10

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
5,365,847.785126743183086247 ANON

Value
$0.00
0x4ce96aacbf4a605084d757141be016de8431b285
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:
ANONToken

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion, MIT license
File 1 of 20 : ANONToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "../libraries/AntiWhaleToken.sol";
import "../libraries/ERC20Base.sol";
import "../libraries/ERC20Burnable.sol";
import "../libraries/TaxableToken.sol";

/**
 * @dev ERC20Token implementation with AccessControl, Burn, AntiWhale, Tax capabilities
 */
contract ANONToken is ERC20Base, AntiWhaleToken, ERC20Burnable, AccessControl, TaxableToken {
    bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
    bytes32 public constant EXCLUDED_FROM_ANTIWHALE_ROLE = keccak256("EXCLUDED_FROM_ANTIWHALE_ROLE");
    bytes32 public constant TAX_ADMIN_ROLE = keccak256("TAX_ADMIN_ROLE");

    constructor(
        uint256 initialSupply_,
        address feeReceiver_,
        address swapRouter_,
        FeeConfiguration memory feeConfiguration_,
        address[] memory collectors_,
        uint256[] memory shares_
    )
        payable
        ERC20Base("Anonymous VC", "ANON", 18, 0x312f313639393932342f412f422f572f54)
        AntiWhaleToken(initialSupply_ / 100) // 1% of supply
        TaxableToken(true, initialSupply_ / 10000, swapRouter_, feeConfiguration_)
        TaxDistributor(collectors_, shares_)
    {
        require(initialSupply_ > 0, "Initial supply cannot be zero");
        payable(feeReceiver_).transfer(msg.value);
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
        _setupRole(EXCLUDED_FROM_ANTIWHALE_ROLE, BURN_ADDRESS);
        _setupRole(EXCLUDED_FROM_ANTIWHALE_ROLE, _msgSender());
        _setupRole(EXCLUDED_FROM_ANTIWHALE_ROLE, swapPair);
        _setupRole(TAX_ADMIN_ROLE, _msgSender());
        _mint(_msgSender(), initialSupply_);
    }

    /**
     * @dev Update the max token allowed per wallet.
     * only callable by members of the `DEFAULT_ADMIN_ROLE`
     */
    function setMaxTokenPerWallet(uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) {
        _setMaxTokenPerWallet(amount);
    }

    /**
     * @dev returns true if address is excluded from anti whale
     */
    function isExcludedFromAntiWhale(address account) public view override returns (bool) {
        return hasRole(EXCLUDED_FROM_ANTIWHALE_ROLE, account);
    }

    /**
     * @dev Destroys `amount` tokens from the caller.
     * only callable by members of the `BURNER_ROLE`
     */
    function burn(uint256 amount) external override onlyRole(BURNER_ROLE) {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     * only callable by members of the `BURNER_ROLE`
     */
    function burnFrom(address account, uint256 amount) external override onlyRole(BURNER_ROLE) {
        _burnFrom(account, amount);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override(ERC20, AntiWhaleToken) {
        super._beforeTokenTransfer(from, to, amount);
    }

    /**
     * @dev Enable/Disable autoProcessFees on transfer
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function setAutoprocessFees(bool autoProcess) external override onlyRole(TAX_ADMIN_ROLE) {
        require(autoProcessFees != autoProcess, "Already set");
        autoProcessFees = autoProcess;
    }

    /**
     * @dev add a fee collector
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function addFeeCollector(address account, uint256 share) external override onlyRole(TAX_ADMIN_ROLE) {
        _addFeeCollector(account, share);
    }

    /**
     * @dev add/remove a LP
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function setIsLpPool(address pairAddress, bool isLp) external override onlyRole(TAX_ADMIN_ROLE) {
        _setIsLpPool(pairAddress, isLp);
    }

    /**
     * @dev add/remove an address to the tax exclusion list
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function setIsExcludedFromFees(address account, bool excluded) external override onlyRole(TAX_ADMIN_ROLE) {
        _setIsExcludedFromFees(account, excluded);
    }

    /**
     * @dev manually distribute fees to collectors
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function distributeFees(uint256 amount, bool inToken) external override onlyRole(TAX_ADMIN_ROLE) {
        if (inToken) {
            require(balanceOf(address(this)) >= amount, "Not enough balance");
        } else {
            require(address(this).balance >= amount, "Not enough balance");
        }
        _distributeFees(amount, inToken);
    }

    /**
     * @dev process fees
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function processFees(uint256 amount, uint256 minAmountOut) external override onlyRole(TAX_ADMIN_ROLE) {
        require(amount <= balanceOf(address(this)), "Amount too high");
        _processFees(amount, minAmountOut);
    }

    /**
     * @dev remove a fee collector
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function removeFeeCollector(address account) external override onlyRole(TAX_ADMIN_ROLE) {
        _removeFeeCollector(account);
    }

    /**
     * @dev set the liquidity owner
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function setLiquidityOwner(address newOwner) external override onlyRole(TAX_ADMIN_ROLE) {
        liquidityOwner = newOwner;
    }

    /**
     * @dev set the number of tokens to swap
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function setNumTokensToSwap(uint256 amount) external override onlyRole(TAX_ADMIN_ROLE) {
        numTokensToSwap = amount;
    }

    /**
     * @dev update a fee collector share
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function updateFeeCollectorShare(address account, uint256 share) external override onlyRole(TAX_ADMIN_ROLE) {
        _updateFeeCollectorShare(account, share);
    }

    /**
     * @dev update the fee configurations
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function setFeeConfiguration(FeeConfiguration calldata configuration) external override onlyRole(TAX_ADMIN_ROLE) {
        _setFeeConfiguration(configuration);
    }

    /**
     * @dev update the swap router
     * only callable by members of the `TAX_ADMIN_ROLE`
     */
    function setSwapRouter(address newRouter) external override onlyRole(TAX_ADMIN_ROLE) {
        _setSwapRouter(newRouter);
    }

    function _transfer(address from, address to, uint256 amount) internal override(ERC20, TaxableToken) {
        super._transfer(from, to, amount);
    }
}

File 2 of 20 : TaxableToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "./ERC20Base.sol";
import "./TaxDistributor.sol";

/*
 * TaxableToken: Add a tax on buy, sell or transfer
 */
abstract contract TaxableToken is ERC20Base, TaxDistributor {
    struct FeeConfiguration {
        bool feesInToken; // if set to true, collectors will get tokens, if false collector the fee will be swapped for the native currency
        uint16 buyFees; // fees applied during buys, from 0 to 2000 (ie, 100 = 1%)
        uint16 sellFees; // fees applied during sells, from 0 to 2000 (ie, 100 = 1%)
        uint16 transferFees; // fees applied during transfers, from 0 to 2000 (ie, 100 = 1%)
        uint16 burnFeeRatio; // from 0 to 10000 (ie 8000 = 80% of the fee collected are burned)
        uint16 liquidityFeeRatio; // from 0 to 10000 (ie 8000 = 80% of the fee collected are added back to liquidity)
        uint16 collectorsFeeRatio; // from 0 to 10000 (ie 8000 = 80% of the fee collected are sent to fee collectors)
    }

    address public constant BURN_ADDRESS = address(0x000000000000000000000000000000000000dEaD);
    uint16 public constant MAX_FEE = 2000; // max 20% fees
    uint16 public constant FEE_PRECISION = 10000;

    // swap config
    IUniswapV2Router02 public swapRouter;
    address public swapPair;
    address public liquidityOwner;

    // fees
    bool private _processingFees;
    bool public autoProcessFees;
    uint256 public numTokensToSwap; // amount of tokens to collect before processing fees (default to 0.05% of supply)
    FeeConfiguration public feeConfiguration;

    mapping(address => bool) private _excludedFromFees;
    mapping(address => bool) private _lpPools;

    event FeeConfigurationUpdated(FeeConfiguration configuration);
    event SwapRouterUpdated(address indexed router, address indexed pair);
    event ExcludedFromFees(address indexed account, bool excluded);
    event SetLpPool(address indexed pairAddress, bool isLp);

    modifier lockTheSwap() {
        _processingFees = true;
        _;
        _processingFees = false;
    }

    constructor(
        bool autoProcessFees_,
        uint256 numTokensToSwap_,
        address swapRouter_,
        FeeConfiguration memory feeConfiguration_
    ) {
        numTokensToSwap = numTokensToSwap_;
        autoProcessFees = autoProcessFees_;

        liquidityOwner = _msgSender();

        // Create a uniswap pair for this new token
        swapRouter = IUniswapV2Router02(swapRouter_);
        swapPair = _pairFor(swapRouter.factory(), address(this), swapRouter.WETH());
        _lpPools[swapPair] = true;

        // configure addresses excluded from fee
        _setIsExcludedFromFees(_msgSender(), true);
        _setIsExcludedFromFees(address(this), true);

        // configure fees
        _setFeeConfiguration(feeConfiguration_);
    }

    // receive ETH when swaping
    receive() external payable {}

    function isExcludedFromFees(address account) public view returns (bool) {
        return _excludedFromFees[account];
    }

    function _setIsExcludedFromFees(address account, bool excluded) internal {
        require(_excludedFromFees[account] != excluded, "Already set");
        _excludedFromFees[account] = excluded;
        emit ExcludedFromFees(account, excluded);
    }

    function _setIsLpPool(address pairAddress, bool isLp) internal {
        require(_lpPools[pairAddress] != isLp, "Already set");
        _lpPools[pairAddress] = isLp;
        emit SetLpPool(pairAddress, isLp);
    }

    function isLpPool(address pairAddress) public view returns (bool) {
        return _lpPools[pairAddress];
    }

    function _setSwapRouter(address _newRouter) internal {
        require(_newRouter != address(0), "Invalid router");

        swapRouter = IUniswapV2Router02(_newRouter);
        IUniswapV2Factory factory = IUniswapV2Factory(swapRouter.factory());
        require(address(factory) != address(0), "Invalid factory");

        address weth = swapRouter.WETH();
        swapPair = factory.getPair(address(this), weth);
        if (swapPair == address(0)) {
            swapPair = factory.createPair(address(this), weth);
        }

        require(swapPair != address(0), "Invalid pair address.");
        emit SwapRouterUpdated(address(swapRouter), swapPair);
    }

    function _setFeeConfiguration(FeeConfiguration memory configuration) internal {
        require(configuration.buyFees <= MAX_FEE, "Invalid buy fee");
        require(configuration.sellFees <= MAX_FEE, "Invalid sell fee");
        require(configuration.transferFees <= MAX_FEE, "Invalid transfer fee");

        uint16 totalShare = configuration.burnFeeRatio +
            configuration.liquidityFeeRatio +
            configuration.collectorsFeeRatio;
        require(totalShare == 0 || totalShare == FEE_PRECISION, "Invalid fee share");

        feeConfiguration = configuration;
        emit FeeConfigurationUpdated(configuration);
    }

    function _processFees(uint256 tokenAmount, uint256 minAmountOut) internal lockTheSwap {
        uint256 contractTokenBalance = balanceOf(address(this));
        if (contractTokenBalance >= tokenAmount) {
            uint256 liquidityAmount = (tokenAmount * feeConfiguration.liquidityFeeRatio) /
                (FEE_PRECISION - feeConfiguration.burnFeeRatio);
            uint256 liquidityTokens = liquidityAmount / 2;

            uint256 collectorsAmount = tokenAmount - liquidityAmount;
            uint256 liquifyAmount = liquidityAmount - liquidityTokens;

            if (!feeConfiguration.feesInToken) {
                liquifyAmount += collectorsAmount;
            }

            // swap tokens
            if (liquifyAmount > 0) {
                if (balanceOf(swapPair) == 0) {
                    // do not swap before the pair has liquidity
                    return;
                }

                // capture the contract's current balance.
                uint256 initialBalance = address(this).balance;

                _swapTokensForEth(liquifyAmount, minAmountOut);

                // how much did we just swap into?
                uint256 swapBalance = address(this).balance - initialBalance;

                // add liquidity
                uint256 liquidityETH = (swapBalance * liquidityTokens) / liquifyAmount;
                if (liquidityETH > 0) {
                    _addLiquidity(liquidityTokens, liquidityETH);
                }
            }

            if (feeConfiguration.feesInToken) {
                // send tokens to fee collectors
                _distributeFees(collectorsAmount, true);
            } else {
                // send remaining ETH to fee collectors
                _distributeFees(address(this).balance, false);
            }
        }
    }

    /// @dev Swap tokens for eth
    function _swapTokensForEth(uint256 tokenAmount, uint256 minAmountOut) private {
        // generate the swap pair path of token -> weth
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = swapRouter.WETH();

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

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

    /// @dev Add liquidity
    function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
        // approve token transfer to cover all possible scenarios
        _approve(address(this), address(swapRouter), tokenAmount);

        // add the liquidity
        swapRouter.addLiquidityETH{value: ethAmount}(
            address(this),
            tokenAmount,
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            liquidityOwner,
            block.timestamp
        );
    }

    // calculates the CREATE2 address for a pair without making any external calls
    function _pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
        (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        pair = address(
            uint160(
                uint(
                    keccak256(
                        abi.encodePacked(
                            hex"ff",
                            factory,
                            keccak256(abi.encodePacked(token0, token1)),
                            hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash
                        )
                    )
                )
            )
        );
    }

    function _transfer(address from, address to, uint256 amount) internal virtual override {
        require(amount > 0, "Transfer <= 0");

        uint256 taxFee = 0;
        bool processFee = !_processingFees && autoProcessFees;

        if (!_processingFees) {
            bool fromExcluded = isExcludedFromFees(from);
            bool toExcluded = isExcludedFromFees(to);

            bool fromLP = isLpPool(from);
            bool toLP = isLpPool(to);

            if (fromLP && !toLP && !toExcluded && to != address(swapRouter)) {
                // buy fee
                taxFee = feeConfiguration.buyFees;
            } else if (toLP && !fromExcluded && !toExcluded) {
                // sell fee
                taxFee = feeConfiguration.sellFees;
            } else if (!fromLP && !toLP && from != address(swapRouter) && !fromExcluded) {
                // transfer fee
                taxFee = feeConfiguration.transferFees;
            }
        }

        // process fees
        if (processFee && taxFee > 0 && !_lpPools[from]) {
            uint256 contractTokenBalance = balanceOf(address(this));
            if (contractTokenBalance >= numTokensToSwap) {
                _processFees(numTokensToSwap, 0);
            }
        }

        if (taxFee > 0) {
            uint256 taxAmount = (amount * taxFee) / FEE_PRECISION;
            uint256 sendAmount = amount - taxAmount;
            uint256 burnAmount = (taxAmount * feeConfiguration.burnFeeRatio) / FEE_PRECISION;

            if (burnAmount > 0) {
                taxAmount -= burnAmount;
                super._transfer(from, BURN_ADDRESS, burnAmount);
            }

            if (taxAmount > 0) {
                super._transfer(from, address(this), taxAmount);
            }

            if (sendAmount > 0) {
                super._transfer(from, to, sendAmount);
            }
        } else {
            super._transfer(from, to, amount);
        }
    }

    function setAutoprocessFees(bool autoProcess) external virtual;

    function setIsLpPool(address pairAddress, bool isLp) external virtual;

    function setIsExcludedFromFees(address account, bool excluded) external virtual;

    function processFees(uint256 amount, uint256 minAmountOut) external virtual;

    function setLiquidityOwner(address newOwner) external virtual;

    function setNumTokensToSwap(uint256 amount) external virtual;

    function setFeeConfiguration(FeeConfiguration calldata configuration) external virtual;

    function setSwapRouter(address newRouter) external virtual;
}

File 3 of 20 : TaxDistributor.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.17;

import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "./ERC20Base.sol";

abstract contract TaxDistributor is ERC20Base {
    using EnumerableSet for EnumerableSet.AddressSet;

    EnumerableSet.AddressSet private _collectors;
    mapping(address => uint256) private _shares;
    uint256 public totalFeeCollectorsShares;

    event FeeCollectorAdded(address indexed account, uint256 share);
    event FeeCollectorUpdated(address indexed account, uint256 oldShare, uint256 newShare);
    event FeeCollectorRemoved(address indexed account);
    event FeeCollected(address indexed receiver, uint256 amount);

    constructor(address[] memory collectors_, uint256[] memory shares_) {
        require(collectors_.length == shares_.length, "Invalid fee collectors");
        for (uint256 i = 0; i < collectors_.length; i++) {
            _addFeeCollector(collectors_[i], shares_[i]);
        }
    }

    function isFeeCollector(address account) public view returns (bool) {
        return _collectors.contains(account);
    }

    function feeCollectorShare(address account) public view returns (uint256) {
        return _shares[account];
    }

    function _addFeeCollector(address account, uint256 share) internal {
        require(!_collectors.contains(account), "Already fee collector");
        require(share > 0, "Invalid share");

        _collectors.add(account);
        _shares[account] = share;
        totalFeeCollectorsShares += share;

        emit FeeCollectorAdded(account, share);
    }

    function _removeFeeCollector(address account) internal {
        require(_collectors.contains(account), "Not fee collector");
        _collectors.remove(account);
        totalFeeCollectorsShares -= _shares[account];
        delete _shares[account];

        emit FeeCollectorRemoved(account);
    }

    function _updateFeeCollectorShare(address account, uint256 share) internal {
        require(_collectors.contains(account), "Not fee collector");
        require(share > 0, "Invalid share");

        uint256 oldShare = _shares[account];
        totalFeeCollectorsShares -= oldShare;

        _shares[account] = share;
        totalFeeCollectorsShares += share;

        emit FeeCollectorUpdated(account, oldShare, share);
    }

    function _distributeFees(uint256 amount, bool inToken) internal returns (bool) {
        if (amount == 0) return false;
        if (totalFeeCollectorsShares == 0) return false;

        uint256 distributed = 0;
        uint256 len = _collectors.length();
        for (uint256 i = 0; i < len; i++) {
            address collector = _collectors.at(i);
            uint256 share = i == len - 1
                ? amount - distributed
                : (amount * _shares[collector]) / totalFeeCollectorsShares;

            if (inToken) {
                _transfer(address(this), collector, share);
            } else {
                payable(collector).transfer(share);
            }
            emit FeeCollected(collector, share);

            distributed += share;
        }

        return true;
    }

    function addFeeCollector(address account, uint256 share) external virtual;

    function removeFeeCollector(address account) external virtual;

    function updateFeeCollectorShare(address account, uint256 share) external virtual;

    function distributeFees(uint256 amount, bool inToken) external virtual;
}

File 4 of 20 : ERC20Burnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20Base {
    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) external virtual {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
     */
    function _burnFrom(address account, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(account, _msgSender());
        require(currentAllowance >= amount, "ERC20Burnable: burn amount exceeds allowance");
        unchecked {
            _approve(account, _msgSender(), currentAllowance - amount);
        }
        _burn(account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     */
    function burnFrom(address account, uint256 amount) external virtual {
        _burnFrom(account, amount);
    }
}

File 5 of 20 : ERC20Base.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

abstract contract ERC20Base is ERC20 {
    uint8 private immutable _decimals;
    uint256 public immutable TOKEN_CODE;

    constructor(
        string memory name_,
        string memory symbol_,
        uint8 decimals_,
        uint256 token_code_
    ) ERC20(name_, symbol_) {
        _decimals = decimals_;
        TOKEN_CODE = token_code_;
    }

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

File 6 of 20 : AntiWhaleToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ERC20Base.sol";

/*
 * AntiWhaleToken: Limit the max wallet size
 */
abstract contract AntiWhaleToken is ERC20Base {
    uint256 public maxTokenPerWallet; // anti whale: max token per wallet (default to 1% of supply)

    event MaxTokenPerWalletUpdated(uint256 amount);

    modifier antiWhale(
        address sender,
        address recipient,
        uint256 amount
    ) {
        if (maxTokenPerWallet != 0 && !isExcludedFromAntiWhale(recipient)) {
            require(balanceOf(recipient) + amount <= maxTokenPerWallet, "Wallet exceeds max");
        }
        _;
    }

    constructor(uint256 maxTokenPerWallet_) {
        maxTokenPerWallet = maxTokenPerWallet_;
    }

    function isExcludedFromAntiWhale(address account) public view virtual returns (bool);

    /**
     * @dev Update the max token per wallet
     * set to 0 to disable
     */
    function _setMaxTokenPerWallet(uint256 amount) internal {
        require(amount == 0 || amount > (totalSupply() * 5) / 1000, "Amount too low"); // min 0.5% of supply

        maxTokenPerWallet = amount;
        emit MaxTokenPerWalletUpdated(amount);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override antiWhale(from, to, amount) {
        super._beforeTokenTransfer(from, to, amount);
    }
}

File 7 of 20 : 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 8 of 20 : 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 9 of 20 : 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 10 of 20 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

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

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

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

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

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

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

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

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

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

            return true;
        } else {
            return false;
        }
    }

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

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

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

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

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

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

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

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

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

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

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

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

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

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

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

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 11 of 20 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

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

pragma solidity ^0.8.0;

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

File 13 of 20 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

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

pragma solidity ^0.8.0;

import "./math/Math.sol";

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

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

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

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

pragma solidity ^0.8.0;

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

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

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

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

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

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

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

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

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

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

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

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

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

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

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

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

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

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

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

File 19 of 20 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

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

pragma solidity ^0.8.0;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(account),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * May emit a {RoleGranted} event.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"initialSupply_","type":"uint256"},{"internalType":"address","name":"feeReceiver_","type":"address"},{"internalType":"address","name":"swapRouter_","type":"address"},{"components":[{"internalType":"bool","name":"feesInToken","type":"bool"},{"internalType":"uint16","name":"buyFees","type":"uint16"},{"internalType":"uint16","name":"sellFees","type":"uint16"},{"internalType":"uint16","name":"transferFees","type":"uint16"},{"internalType":"uint16","name":"burnFeeRatio","type":"uint16"},{"internalType":"uint16","name":"liquidityFeeRatio","type":"uint16"},{"internalType":"uint16","name":"collectorsFeeRatio","type":"uint16"}],"internalType":"struct TaxableToken.FeeConfiguration","name":"feeConfiguration_","type":"tuple"},{"internalType":"address[]","name":"collectors_","type":"address[]"},{"internalType":"uint256[]","name":"shares_","type":"uint256[]"}],"stateMutability":"payable","type":"constructor"},{"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":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"excluded","type":"bool"}],"name":"ExcludedFromFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"share","type":"uint256"}],"name":"FeeCollectorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"FeeCollectorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldShare","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newShare","type":"uint256"}],"name":"FeeCollectorUpdated","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bool","name":"feesInToken","type":"bool"},{"internalType":"uint16","name":"buyFees","type":"uint16"},{"internalType":"uint16","name":"sellFees","type":"uint16"},{"internalType":"uint16","name":"transferFees","type":"uint16"},{"internalType":"uint16","name":"burnFeeRatio","type":"uint16"},{"internalType":"uint16","name":"liquidityFeeRatio","type":"uint16"},{"internalType":"uint16","name":"collectorsFeeRatio","type":"uint16"}],"indexed":false,"internalType":"struct TaxableToken.FeeConfiguration","name":"configuration","type":"tuple"}],"name":"FeeConfigurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MaxTokenPerWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pairAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"isLp","type":"bool"}],"name":"SetLpPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"router","type":"address"},{"indexed":true,"internalType":"address","name":"pair","type":"address"}],"name":"SwapRouterUpdated","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":[],"name":"BURNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BURN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXCLUDED_FROM_ANTIWHALE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_PRECISION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TAX_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_CODE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"share","type":"uint256"}],"name":"addFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"autoProcessFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"inToken","type":"bool"}],"name":"distributeFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"feeCollectorShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeConfiguration","outputs":[{"internalType":"bool","name":"feesInToken","type":"bool"},{"internalType":"uint16","name":"buyFees","type":"uint16"},{"internalType":"uint16","name":"sellFees","type":"uint16"},{"internalType":"uint16","name":"transferFees","type":"uint16"},{"internalType":"uint16","name":"burnFeeRatio","type":"uint16"},{"internalType":"uint16","name":"liquidityFeeRatio","type":"uint16"},{"internalType":"uint16","name":"collectorsFeeRatio","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromAntiWhale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isFeeCollector","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pairAddress","type":"address"}],"name":"isLpPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTokenPerWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numTokensToSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"processFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"autoProcess","type":"bool"}],"name":"setAutoprocessFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"feesInToken","type":"bool"},{"internalType":"uint16","name":"buyFees","type":"uint16"},{"internalType":"uint16","name":"sellFees","type":"uint16"},{"internalType":"uint16","name":"transferFees","type":"uint16"},{"internalType":"uint16","name":"burnFeeRatio","type":"uint16"},{"internalType":"uint16","name":"liquidityFeeRatio","type":"uint16"},{"internalType":"uint16","name":"collectorsFeeRatio","type":"uint16"}],"internalType":"struct TaxableToken.FeeConfiguration","name":"configuration","type":"tuple"}],"name":"setFeeConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"excluded","type":"bool"}],"name":"setIsExcludedFromFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pairAddress","type":"address"},{"internalType":"bool","name":"isLp","type":"bool"}],"name":"setIsLpPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setLiquidityOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMaxTokenPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setNumTokensToSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRouter","type":"address"}],"name":"setSwapRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFeeCollectorsShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"share","type":"uint256"}],"name":"updateFeeCollectorShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c06040526040516200472e3803806200472e833981016040819052620000269162000ef0565b600162000036612710886200104f565b858585856200004760648d6200104f565b6040518060400160405280600c81526020016b416e6f6e796d6f757320564360a01b8152506040518060400160405280600481526020016320a727a760e11b815250601270312f313639393932342f412f422f572f5483838160039081620000b09190620010f8565b506004620000bf8282620010f8565b50505060ff90911660805260a05250506005558051825114620001295760405162461bcd60e51b815260206004820152601660248201527f496e76616c69642066656520636f6c6c6563746f72730000000000000000000060448201526064015b60405180910390fd5b60005b82518110156200019557620001808382815181106200014f576200014f620011c4565b60200260200101518383815181106200016c576200016c620011c4565b60200260200101516200046960201b60201c565b806200018c81620011da565b9150506200012c565b505050600e839055600d805460ff60a81b1916600160a81b86151502179055620001bc3390565b600d80546001600160a01b039283166001600160a01b031991821617909155600b805492851692909116821790556040805163c45a015560e01b81529051620002c7929163c45a01559160048083019260209291908290030181865afa1580156200022b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002519190620011f6565b600b54604080516315ab88c960e31b8152905130926001600160a01b03169163ad5c46489160048083019260209291908290030181865afa1580156200029b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002c19190620011f6565b6200058c565b600c80546001600160a01b0319166001600160a01b039290921691821790556000908152601160205260409020805460ff19166001179055620003136200030b3390565b60016200068f565b620003203060016200068f565b6200032b8162000748565b5050505060008611620003815760405162461bcd60e51b815260206004820152601d60248201527f496e697469616c20737570706c792063616e6e6f74206265207a65726f000000604482015260640162000120565b6040516001600160a01b038616903480156108fc02916000818181858888f19350505050158015620003b7573d6000803e3d6000fd5b50620003c560003362000a3e565b620003e26000805160206200470e83398151915261dead62000a3e565b620003fd6000805160206200470e8339815191523362000a3e565b600c5462000425906000805160206200470e833981519152906001600160a01b031662000a3e565b620004517fcaa508224cbc2c612b91345550b57fa87a9308bdc3d83a613f48278c1ef824853362000a3e565b6200045d338762000a4e565b5050505050506200124f565b6200047660078362000b1f565b15620004c55760405162461bcd60e51b815260206004820152601560248201527f416c72656164792066656520636f6c6c6563746f720000000000000000000000604482015260640162000120565b60008111620005075760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b604482015260640162000120565b6200051460078362000b46565b506001600160a01b0382166000908152600960205260408120829055600a80548392906200054490849062001214565b90915550506040518181526001600160a01b038316907f918584c21fe4a093f5014c0dabaed3e43b642781e27984aef122cae8245fbb23906020015b60405180910390a25050565b6000806000836001600160a01b0316856001600160a01b031610620005b3578385620005b6565b84845b6040516001600160601b0319606084811b8216602084015283901b16603482015291935091508690604801604051602081830303815290604052805190602001206040516020016200066d9291907fff00000000000000000000000000000000000000000000000000000000000000815260609290921b6001600160601b031916600183015260158201527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b6001600160a01b03821660009081526010602052604090205481151560ff909116151503620006ef5760405162461bcd60e51b815260206004820152600b60248201526a105b1c9958591e481cd95d60aa1b604482015260640162000120565b6001600160a01b038216600081815260106020908152604091829020805460ff191685151590811790915591519182527f3499bfcf9673677ba552f3fe2ea274ec7e6246da31c3c87e115b45a9b0db2efb910162000580565b6107d061ffff16816020015161ffff1611156200079a5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206275792066656560881b604482015260640162000120565b6107d061ffff16816040015161ffff161115620007ed5760405162461bcd60e51b815260206004820152601060248201526f496e76616c69642073656c6c2066656560801b604482015260640162000120565b6107d061ffff16816060015161ffff1611156200084d5760405162461bcd60e51b815260206004820152601460248201527f496e76616c6964207472616e7366657220666565000000000000000000000000604482015260640162000120565b60008160c001518260a0015183608001516200086a91906200122a565b6200087691906200122a565b905061ffff811615806200088f575061ffff8116612710145b620008d15760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642066656520736861726560781b604482015260640162000120565b8151600f805460208501516040808701516060880151608089015160a08a015160c08b015161ffff9081166b0100000000000000000000000261ffff60581b1992821669010000000000000000000261ffff60481b19948316670100000000000000029490941663ffffffff60381b19958316650100000000000261ffff60281b199784166301000000029790971666ffffffff00000019939099166101000262ffff00199c15159c909c1662ffffff19909a16999099179a909a1716959095179290921716939093179290921716929092179055517ff34b49a91d91598b7774795175736ebf4db4fa5a4edf72772cf50fb27c135efd9062000a32908490600060e082019050825115158252602083015161ffff80821660208501528060408601511660408501528060608601511660608501528060808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b60405180910390a15050565b62000a4a828262000b5d565b5050565b6001600160a01b03821662000aa65760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640162000120565b62000ab46000838362000c01565b806002600082825462000ac8919062001214565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b038116600090815260018301602052604081205415155b90505b92915050565b600062000b3d836001600160a01b03841662000c13565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff1662000a4a5760008281526006602090815260408083206001600160a01b03851684529091529020805460ff1916600117905562000bbd3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b62000c0e83838362000c65565b505050565b600081815260018301602052604081205462000c5c5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000b40565b50600062000b40565b82828260055460001415801562000c84575062000c828262000d07565b155b1562000cff576005548162000cae846001600160a01b031660009081526020819052604090205490565b62000cba919062001214565b111562000cff5760405162461bcd60e51b81526020600482015260126024820152710aec2d8d8cae840caf0c6cacac8e640dac2f60731b604482015260640162000120565b505050505050565b6001600160a01b03811660009081527fe3c409d54039d66586f458c2b7d6d78dff5fb18c24d32eed4011358c6e316201602052604081205460ff1662000b40565b80516001600160a01b038116811462000d6057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b038111828210171562000da05762000da062000d65565b60405290565b604051601f8201601f191681016001600160401b038111828210171562000dd15762000dd162000d65565b604052919050565b805161ffff8116811462000d6057600080fd5b60006001600160401b0382111562000e085762000e0862000d65565b5060051b60200190565b600082601f83011262000e2457600080fd5b8151602062000e3d62000e378362000dec565b62000da6565b82815260059290921b8401810191818101908684111562000e5d57600080fd5b8286015b8481101562000e835762000e758162000d48565b835291830191830162000e61565b509695505050505050565b600082601f83011262000ea057600080fd5b8151602062000eb362000e378362000dec565b82815260059290921b8401810191818101908684111562000ed357600080fd5b8286015b8481101562000e83578051835291830191830162000ed7565b60008060008060008086880361018081121562000f0c57600080fd5b8751965062000f1e6020890162000d48565b955062000f2e6040890162000d48565b945060e0605f198201121562000f4357600080fd5b5062000f4e62000d7b565b6060880151801515811462000f6257600080fd5b815262000f726080890162000dd9565b602082015262000f8560a0890162000dd9565b604082015262000f9860c0890162000dd9565b606082015262000fab60e0890162000dd9565b608082015262000fbf610100890162000dd9565b60a082015262000fd3610120890162000dd9565b60c08201526101408801519093506001600160401b038082111562000ff757600080fd5b620010058a838b0162000e12565b93506101608901519150808211156200101d57600080fd5b506200102c89828a0162000e8e565b9150509295509295509295565b634e487b7160e01b600052601160045260246000fd5b6000826200106d57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806200108757607f821691505b602082108103620010a857634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000c0e57600081815260208120601f850160051c81016020861015620010d75750805b601f850160051c820191505b8181101562000cff57828155600101620010e3565b81516001600160401b0381111562001114576200111462000d65565b6200112c8162001125845462001072565b84620010ae565b602080601f8311600181146200116457600084156200114b5750858301515b600019600386901b1c1916600185901b17855562000cff565b600085815260208120601f198616915b82811015620011955788860151825594840194600190910190840162001174565b5085821015620011b45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b600060018201620011ef57620011ef62001039565b5060010190565b6000602082840312156200120957600080fd5b62000b3d8262000d48565b8082018082111562000b405762000b4062001039565b61ffff81811683821601908082111562001248576200124862001039565b5092915050565b60805160a0516134996200127560003960006104190152600061058001526134996000f3fe60806040526004361061031e5760003560e01c80636f741f2a116101ab578063a457c2d7116100f7578063c31c9c0711610095578063e55096b01161006f578063e55096b014610a83578063e63a391f14610aa3578063f4232d2514610ab9578063fccc281314610ad957600080fd5b8063c31c9c0714610a23578063d547741f14610a43578063dd62ed3e14610a6357600080fd5b8063b3c20ebd116100d1578063b3c20ebd146109a2578063b3c6e9ee146109c4578063bc063e1a146109da578063bd82394314610a0357600080fd5b8063a457c2d714610942578063a9059cbb14610962578063adf186931461098257600080fd5b80638e3166bc1161016457806395d89b411161013e57806395d89b411461085c57806398c47e8c146108715780639b61f1d01461090c578063a217fddf1461092d57600080fd5b80638e3166bc146107d257806391d148541461080657806394b8a7031461082657600080fd5b80636f741f2a1461070357806370a082311461073c57806372bc55831461075c57806379cc67901461077c5780637a8baf521461079c5780637f5bbb2c146107b257600080fd5b8063282c51f31161026a578063395093511161022357806342966c68116101fd57806342966c681461066a5780634569c4451461068a578063490e5147146106aa5780634fbee193146106ca57600080fd5b8063395093511461060a5780633b90b9bf1461062a578063412736571461064a57600080fd5b8063282c51f3146105185780632f2ff15d1461054c578063313ce5671461056c5780633502628a146105aa57806336568abe146105ca5780633935ebf9146105ea57600080fd5b806312363f4a116102d757806323b872dd116102b157806323b872dd14610470578063248a9ca31461049057806326991cc8146104c0578063269f534c146104f857600080fd5b806312363f4a1461040757806318160ddd1461043b5780631fa67b4d1461045057600080fd5b806301a6c43b1461032a57806301ffc9a71461035357806306fdde0314610383578063095ea7b3146103a55780630a4e42ef146103c55780630f569dad146103e757600080fd5b3661032557005b600080fd5b34801561033657600080fd5b50610340600e5481565b6040519081526020015b60405180910390f35b34801561035f57600080fd5b5061037361036e366004612e73565b610aef565b604051901515815260200161034a565b34801561038f57600080fd5b50610398610b26565b60405161034a9190612ec1565b3480156103b157600080fd5b506103736103c0366004612f09565b610bb8565b3480156103d157600080fd5b506103e56103e0366004612f35565b610bd0565b005b3480156103f357600080fd5b506103e5610402366004612f57565b610c46565b34801561041357600080fd5b506103407f000000000000000000000000000000000000000000000000000000000000000081565b34801561044757600080fd5b50600254610340565b34801561045c57600080fd5b506103e561046b366004612f70565b610c64565b34801561047c57600080fd5b5061037361048b366004612f8d565b610c89565b34801561049c57600080fd5b506103406104ab366004612f57565b60009081526006602052604090206001015490565b3480156104cc57600080fd5b50600c546104e0906001600160a01b031681565b6040516001600160a01b03909116815260200161034a565b34801561050457600080fd5b50610373610513366004612f70565b610cad565b34801561052457600080fd5b506103407f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84881565b34801561055857600080fd5b506103e5610567366004612fce565b610cd9565b34801561057857600080fd5b5060405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161034a565b3480156105b657600080fd5b506103e56105c5366004612f09565b610cfe565b3480156105d657600080fd5b506103e56105e5366004612fce565b610d20565b3480156105f657600080fd5b50600d546104e0906001600160a01b031681565b34801561061657600080fd5b50610373610625366004612f09565b610d9a565b34801561063657600080fd5b50610373610645366004612f70565b610dbc565b34801561065657600080fd5b506103e5610665366004612f70565b610dc9565b34801561067657600080fd5b506103e5610685366004612f57565b610dea565b34801561069657600080fd5b506103e56106a5366004613013565b610e1e565b3480156106b657600080fd5b506103e56106c536600461303f565b610ee3565b3480156106d657600080fd5b506103736106e5366004612f70565b6001600160a01b031660009081526010602052604090205460ff1690565b34801561070f57600080fd5b5061037361071e366004612f70565b6001600160a01b031660009081526011602052604090205460ff1690565b34801561074857600080fd5b50610340610757366004612f70565b610f12565b34801561076857600080fd5b506103e5610777366004612f70565b610f2d565b34801561078857600080fd5b506103e5610797366004612f09565b610f68565b3480156107a857600080fd5b5061034060055481565b3480156107be57600080fd5b506103e56107cd366004613057565b610f9c565b3480156107de57600080fd5b506103407f5df7ebf31955a926cc63dac31c1a31bc588cdae5c3e13e63b89ebfe0eaba875381565b34801561081257600080fd5b50610373610821366004612fce565b611005565b34801561083257600080fd5b50610340610841366004612f70565b6001600160a01b031660009081526009602052604090205490565b34801561086857600080fd5b50610398611030565b34801561087d57600080fd5b50600f546108ca9060ff81169061ffff610100820481169163010000008104821691650100000000008204811691600160381b8104821691600160481b8204811691600160581b90041687565b60408051971515885261ffff968716602089015294861694870194909452918416606086015283166080850152821660a08401521660c082015260e00161034a565b34801561091857600080fd5b50600d5461037390600160a81b900460ff1681565b34801561093957600080fd5b50610340600081565b34801561094e57600080fd5b5061037361095d366004612f09565b61103f565b34801561096e57600080fd5b5061037361097d366004612f09565b6110ba565b34801561098e57600080fd5b506103e561099d366004613072565b6110c8565b3480156109ae57600080fd5b5061034060008051602061344483398151915281565b3480156109d057600080fd5b50610340600a5481565b3480156109e657600080fd5b506109f06107d081565b60405161ffff909116815260200161034a565b348015610a0f57600080fd5b506103e5610a1e366004612f57565b6110ea565b348015610a2f57600080fd5b50600b546104e0906001600160a01b031681565b348015610a4f57600080fd5b506103e5610a5e366004612fce565b6110fe565b348015610a6f57600080fd5b50610340610a7e36600461309e565b611123565b348015610a8f57600080fd5b506103e5610a9e366004613072565b61114e565b348015610aaf57600080fd5b506109f061271081565b348015610ac557600080fd5b506103e5610ad4366004612f09565b611170565b348015610ae557600080fd5b506104e061dead81565b60006001600160e01b03198216637965db0b60e01b1480610b2057506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060038054610b35906130cc565b80601f0160208091040260200160405190810160405280929190818152602001828054610b61906130cc565b8015610bae5780601f10610b8357610100808354040283529160200191610bae565b820191906000526020600020905b815481529060010190602001808311610b9157829003601f168201915b5050505050905090565b600033610bc6818585611192565b5060019392505050565b600080516020613444833981519152610be8816112b6565b610bf130610f12565b831115610c375760405162461bcd60e51b815260206004820152600f60248201526e082dadeeadce840e8dede40d0d2ced608b1b60448201526064015b60405180910390fd5b610c4183836112c3565b505050565b600080516020613444833981519152610c5e816112b6565b50600e55565b600080516020613444833981519152610c7c816112b6565b610c8582611425565b5050565b600033610c978582856114f1565b610ca2858585611565565b506001949350505050565b6000610b207f5df7ebf31955a926cc63dac31c1a31bc588cdae5c3e13e63b89ebfe0eaba875383611005565b600082815260066020526040902060010154610cf4816112b6565b610c418383611570565b600080516020613444833981519152610d16816112b6565b610c4183836115f6565b6001600160a01b0381163314610d905760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610c2e565b610c858282611707565b600033610bc6818585610dad8383611123565b610db79190613116565b611192565b6000610b2060078361176e565b600080516020613444833981519152610de1816112b6565b610c8582611793565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848610e14816112b6565b610c853383611ad0565b600080516020613444833981519152610e36816112b6565b8115610e8e5782610e4630610f12565b1015610e895760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606401610c2e565b610ed3565b82471015610ed35760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606401610c2e565b610edd8383611c0e565b50505050565b600080516020613444833981519152610efb816112b6565b610c85610f0d36849003840184613151565b611d6d565b6001600160a01b031660009081526020819052604090205490565b600080516020613444833981519152610f45816112b6565b50600d80546001600160a01b0319166001600160a01b0392909216919091179055565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848610f92816112b6565b610c418383612046565b600080516020613444833981519152610fb4816112b6565b811515600d60159054906101000a900460ff16151503610fe65760405162461bcd60e51b8152600401610c2e9061320f565b50600d8054911515600160a81b0260ff60a81b19909216919091179055565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b606060048054610b35906130cc565b6000338161104d8286611123565b9050838110156110ad5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610c2e565b610ca28286868403611192565b600033610bc6818585611565565b6000805160206134448339815191526110e0816112b6565b610c4183836120d0565b60006110f5816112b6565b610c8582612168565b600082815260066020526040902060010154611119816112b6565b610c418383611707565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600080516020613444833981519152611166816112b6565b610c41838361220c565b600080516020613444833981519152611188816112b6565b610c4183836122a4565b6001600160a01b0383166111f45760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c2e565b6001600160a01b0382166112555760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c2e565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6112c081336123db565b50565b600d805460ff60a01b1916600160a01b17905560006112e130610f12565b905082811061141257600f5460009061130790600160381b900461ffff16612710613234565b600f5461ffff9182169161132391600160481b9004168661324f565b61132d9190613266565b9050600061133c600283613266565b9050600061134a8387613288565b905060006113588385613288565b600f5490915060ff166113725761136f8282613116565b90505b80156113e457600c5461138d906001600160a01b0316610f12565b60000361139e575050505050611414565b476113a98288612434565b60006113b58247613288565b90506000836113c4878461324f565b6113ce9190613266565b905080156113e0576113e0868261258e565b5050505b600f5460ff1615611400576113fa826001611c0e565b5061140d565b61140b476000611c0e565b505b505050505b505b5050600d805460ff60a01b19169055565b61143060078261176e565b6114705760405162461bcd60e51b81526020600482015260116024820152702737ba103332b29031b7b63632b1ba37b960791b6044820152606401610c2e565b61147b600782612642565b506001600160a01b038116600090815260096020526040812054600a8054919290916114a8908490613288565b90915550506001600160a01b038116600081815260096020526040808220829055517f904316769e154356a5e4aad5d41591b55913c7717fab281d818c1fed7d80e8149190a250565b60006114fd8484611123565b90506000198114610edd57818110156115585760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610c2e565b610edd8484848403611192565b610c41838383612657565b61157a8282611005565b610c855760008281526006602090815260408083206001600160a01b03851684529091529020805460ff191660011790556115b23390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61160160078361176e565b156116465760405162461bcd60e51b815260206004820152601560248201527420b63932b0b23c903332b29031b7b63632b1ba37b960591b6044820152606401610c2e565b600081116116865760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b6044820152606401610c2e565b6116916007836128ea565b506001600160a01b0382166000908152600960205260408120829055600a80548392906116bf908490613116565b90915550506040518181526001600160a01b038316907f918584c21fe4a093f5014c0dabaed3e43b642781e27984aef122cae8245fbb23906020015b60405180910390a25050565b6117118282611005565b15610c855760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6001600160a01b0381166117da5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b2103937baba32b960911b6044820152606401610c2e565b600b80546001600160a01b0319166001600160a01b0383169081179091556040805163c45a015560e01b815290516000929163c45a01559160048083019260209291908290030181865afa158015611836573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185a919061329b565b90506001600160a01b0381166118a45760405162461bcd60e51b815260206004820152600f60248201526e496e76616c696420666163746f727960881b6044820152606401610c2e565b600b54604080516315ab88c960e31b815290516000926001600160a01b03169163ad5c46489160048083019260209291908290030181865afa1580156118ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611912919061329b565b60405163e6a4390560e01b81523060048201526001600160a01b0380831660248301529192509083169063e6a4390590604401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611986919061329b565b600c80546001600160a01b0319166001600160a01b03929092169182179055611a3c576040516364e329cb60e11b81523060048201526001600160a01b03828116602483015283169063c9c65396906044016020604051808303816000875af11580156119f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1b919061329b565b600c80546001600160a01b0319166001600160a01b03929092169190911790555b600c546001600160a01b0316611a8c5760405162461bcd60e51b815260206004820152601560248201527424b73b30b634b2103830b4b91030b2323932b9b99760591b6044820152606401610c2e565b600c54600b546040516001600160a01b0392831692909116907fca394f95d8dbf1e8b2e76b9a8da90cacce1da85181a65508dab13212dc1df53b90600090a3505050565b6001600160a01b038216611b305760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c2e565b611b3c826000836128ff565b6001600160a01b03821660009081526020819052604090205481811015611bb05760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610c2e565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b600082600003611c2057506000610b20565b600a54600003611c3257506000610b20565b600080611c3f600761290a565b905060005b81811015611d61576000611c59600783612914565b90506000611c68600185613288565b8314611ca357600a546001600160a01b038316600090815260096020526040902054611c94908a61324f565b611c9e9190613266565b611cad565b611cad8589613288565b90508615611cc557611cc0308383611565565b611cfd565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611cfb573d6000803e3d6000fd5b505b816001600160a01b03167f06c5efeff5c320943d265dc4e5f1af95ad523555ce0c1957e367dda5514572df82604051611d3891815260200190565b60405180910390a2611d4a8186613116565b945050508080611d59906132b8565b915050611c44565b50600195945050505050565b6107d061ffff16816020015161ffff161115611dbd5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206275792066656560881b6044820152606401610c2e565b6107d061ffff16816040015161ffff161115611e0e5760405162461bcd60e51b815260206004820152601060248201526f496e76616c69642073656c6c2066656560801b6044820152606401610c2e565b6107d061ffff16816060015161ffff161115611e635760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964207472616e736665722066656560601b6044820152606401610c2e565b60008160c001518260a001518360800151611e7e91906132d1565b611e8891906132d1565b905061ffff81161580611ea0575061ffff8116612710145b611ee05760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642066656520736861726560781b6044820152606401610c2e565b8151600f805460208501516040808701516060880151608089015160a08a015160c08b015161ffff908116600160581b0261ffff60581b19928216600160481b026affff00000000000000000019948316600160381b02949094166affffffff0000000000000019958316650100000000000266ffff0000000000199784166301000000029790971666ffffffff00000019939099166101000262ffff00199c15159c909c1662ffffff19909a16999099179a909a1716959095179290921716939093179290921716929092179055517ff34b49a91d91598b7774795175736ebf4db4fa5a4edf72772cf50fb27c135efd9061203a908490600060e082019050825115158252602083015161ffff80821660208501528060408601511660408501528060608601511660608501528060808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b60405180910390a15050565b60006120528333611123565b9050818110156120b95760405162461bcd60e51b815260206004820152602c60248201527f45524332304275726e61626c653a206275726e20616d6f756e7420657863656560448201526b647320616c6c6f77616e636560a01b6064820152608401610c2e565b6120c68333848403611192565b610c418383611ad0565b6001600160a01b03821660009081526010602052604090205481151560ff9091161515036121105760405162461bcd60e51b8152600401610c2e9061320f565b6001600160a01b038216600081815260106020908152604091829020805460ff191685151590811790915591519182527f3499bfcf9673677ba552f3fe2ea274ec7e6246da31c3c87e115b45a9b0db2efb91016116fb565b80158061219457506103e861217c60025490565b61218790600561324f565b6121919190613266565b81115b6121d15760405162461bcd60e51b815260206004820152600e60248201526d416d6f756e7420746f6f206c6f7760901b6044820152606401610c2e565b60058190556040518181527f0271c3ca991d8fa13fc3df55bfd888e9347a178a375ef6e0f63afa9639d144f49060200160405180910390a150565b6001600160a01b03821660009081526011602052604090205481151560ff90911615150361224c5760405162461bcd60e51b8152600401610c2e9061320f565b6001600160a01b038216600081815260116020908152604091829020805460ff191685151590811790915591519182527f902b2ea0acdec5a260e398590d055fe29bd61ef5dd41e45db54a4cd98d5569e091016116fb565b6122af60078361176e565b6122ef5760405162461bcd60e51b81526020600482015260116024820152702737ba103332b29031b7b63632b1ba37b960791b6044820152606401610c2e565b6000811161232f5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b6044820152606401610c2e565b6001600160a01b038216600090815260096020526040812054600a80549192839261235b908490613288565b90915550506001600160a01b0383166000908152600960205260408120839055600a805484929061238d908490613116565b909155505060408051828152602081018490526001600160a01b038516917fd350c3685bdab1285c0b97ffb6e96d96ed0ad4578a135c38250e771e7cb831aa910160405180910390a2505050565b6123e58282611005565b610c85576123f281612920565b6123fd836020612932565b60405160200161240e9291906132ec565b60408051601f198184030181529082905262461bcd60e51b8252610c2e91600401612ec1565b604080516002808252606082018352600092602083019080368337019050509050308160008151811061246957612469613361565b6001600160a01b03928316602091820292909201810191909152600b54604080516315ab88c960e31b81529051919093169263ad5c46489260048083019391928290030181865afa1580156124c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e6919061329b565b816001815181106124f9576124f9613361565b6001600160a01b039283166020918202929092010152600b5461251f9130911685611192565b600b5460405163791ac94760e01b81526001600160a01b039091169063791ac947906125579086908690869030904290600401613377565b600060405180830381600087803b15801561257157600080fd5b505af1158015612585573d6000803e3d6000fd5b50505050505050565b600b546125a69030906001600160a01b031684611192565b600b54600d5460405163f305d71960e01b81523060048201526024810185905260006044820181905260648201526001600160a01b0391821660848201524260a482015291169063f305d71990839060c40160606040518083038185885af1158015612616573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061263b91906133e8565b5050505050565b600061178c836001600160a01b038416612ace565b600081116126975760405162461bcd60e51b815260206004820152600d60248201526c05472616e73666572203c3d203609c1b6044820152606401610c2e565b600d546000908190600160a01b900460ff161580156126bf5750600d54600160a81b900460ff165b600d54909150600160a01b900460ff166127df576001600160a01b03858116600081815260106020908152604080832054948916808452818420549484526011909252808320549183529091205460ff93841693928316929182169116818015612727575080155b8015612731575082155b801561274b5750600b546001600160a01b03898116911614155b1561276357600f54610100900461ffff1695506127da565b80801561276e575083155b8015612778575082155b1561279257600f546301000000900461ffff1695506127da565b8115801561279e575080155b80156127b85750600b546001600160a01b038a8116911614155b80156127c2575083155b156127da57600f5465010000000000900461ffff1695505b505050505b8080156127ec5750600082115b801561281157506001600160a01b03851660009081526011602052604090205460ff16155b1561283b57600061282130610f12565b9050600e54811061283957612839600e5460006112c3565b505b81156128df576000612710612850848661324f565b61285a9190613266565b905060006128688286613288565b600f549091506000906127109061288a90600160381b900461ffff168561324f565b6128949190613266565b905080156128b5576128a68184613288565b92506128b58861dead83612bc8565b82156128c6576128c6883085612bc8565b81156128d7576128d7888884612bc8565b50505061263b565b61263b858585612bc8565b600061178c836001600160a01b038416612d77565b610c41838383612dc6565b6000610b20825490565b600061178c8383612e49565b6060610b206001600160a01b03831660145b6060600061294183600261324f565b61294c906002613116565b67ffffffffffffffff81111561296457612964613129565b6040519080825280601f01601f19166020018201604052801561298e576020820181803683370190505b509050600360fc1b816000815181106129a9576129a9613361565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106129d8576129d8613361565b60200101906001600160f81b031916908160001a90535060006129fc84600261324f565b612a07906001613116565b90505b6001811115612a7f576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612a3b57612a3b613361565b1a60f81b828281518110612a5157612a51613361565b60200101906001600160f81b031916908160001a90535060049490941c93612a7881613416565b9050612a0a565b50831561178c5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610c2e565b60008181526001830160205260408120548015612bb7576000612af2600183613288565b8554909150600090612b0690600190613288565b9050818114612b6b576000866000018281548110612b2657612b26613361565b9060005260206000200154905080876000018481548110612b4957612b49613361565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612b7c57612b7c61342d565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610b20565b6000915050610b20565b5092915050565b6001600160a01b038316612c2c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c2e565b6001600160a01b038216612c8e5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c2e565b612c998383836128ff565b6001600160a01b03831660009081526020819052604090205481811015612d115760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610c2e565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610edd565b6000818152600183016020526040812054612dbe57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610b20565b506000610b20565b828282600554600014158015612de25750612de082610cad565b155b15612e415760055481612df484610f12565b612dfe9190613116565b1115612e415760405162461bcd60e51b81526020600482015260126024820152710aec2d8d8cae840caf0c6cacac8e640dac2f60731b6044820152606401610c2e565b505050505050565b6000826000018281548110612e6057612e60613361565b9060005260206000200154905092915050565b600060208284031215612e8557600080fd5b81356001600160e01b03198116811461178c57600080fd5b60005b83811015612eb8578181015183820152602001612ea0565b50506000910152565b6020815260008251806020840152612ee0816040850160208701612e9d565b601f01601f19169190910160400192915050565b6001600160a01b03811681146112c057600080fd5b60008060408385031215612f1c57600080fd5b8235612f2781612ef4565b946020939093013593505050565b60008060408385031215612f4857600080fd5b50508035926020909101359150565b600060208284031215612f6957600080fd5b5035919050565b600060208284031215612f8257600080fd5b813561178c81612ef4565b600080600060608486031215612fa257600080fd5b8335612fad81612ef4565b92506020840135612fbd81612ef4565b929592945050506040919091013590565b60008060408385031215612fe157600080fd5b823591506020830135612ff381612ef4565b809150509250929050565b8035801515811461300e57600080fd5b919050565b6000806040838503121561302657600080fd5b8235915061303660208401612ffe565b90509250929050565b600060e0828403121561305157600080fd5b50919050565b60006020828403121561306957600080fd5b61178c82612ffe565b6000806040838503121561308557600080fd5b823561309081612ef4565b915061303660208401612ffe565b600080604083850312156130b157600080fd5b82356130bc81612ef4565b91506020830135612ff381612ef4565b600181811c908216806130e057607f821691505b60208210810361305157634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610b2057610b20613100565b634e487b7160e01b600052604160045260246000fd5b803561ffff8116811461300e57600080fd5b600060e0828403121561316357600080fd5b60405160e0810181811067ffffffffffffffff8211171561319457634e487b7160e01b600052604160045260246000fd5b6040526131a083612ffe565b81526131ae6020840161313f565b60208201526131bf6040840161313f565b60408201526131d06060840161313f565b60608201526131e16080840161313f565b60808201526131f260a0840161313f565b60a082015261320360c0840161313f565b60c08201529392505050565b6020808252600b908201526a105b1c9958591e481cd95d60aa1b604082015260600190565b61ffff828116828216039080821115612bc157612bc1613100565b8082028115828204841417610b2057610b20613100565b60008261328357634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610b2057610b20613100565b6000602082840312156132ad57600080fd5b815161178c81612ef4565b6000600182016132ca576132ca613100565b5060010190565b61ffff818116838216019080821115612bc157612bc1613100565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613324816017850160208801612e9d565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613355816028840160208801612e9d565b01602801949350505050565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156133c75784516001600160a01b0316835293830193918301916001016133a2565b50506001600160a01b03969096166060850152505050608001529392505050565b6000806000606084860312156133fd57600080fd5b8351925060208401519150604084015190509250925092565b60008161342557613425613100565b506000190190565b634e487b7160e01b600052603160045260246000fdfecaa508224cbc2c612b91345550b57fa87a9308bdc3d83a613f48278c1ef82485a2646970667358221220f4f556e7fa0da4ef89bb1c88f77c2cdf6e41fd7c1380b97cd9f5c0a094948e3864736f6c634300081300335df7ebf31955a926cc63dac31c1a31bc588cdae5c3e13e63b89ebfe0eaba87530000000000000000000000000000000000000000033b2e3c9fd0803ce8000000000000000000000000000000eb2a9ee506c18566f826849b3c56deb7ff67d8050000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000028168a117d819d2bcfc3598031262767c4054ec000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000002710

Deployed Bytecode

0x60806040526004361061031e5760003560e01c80636f741f2a116101ab578063a457c2d7116100f7578063c31c9c0711610095578063e55096b01161006f578063e55096b014610a83578063e63a391f14610aa3578063f4232d2514610ab9578063fccc281314610ad957600080fd5b8063c31c9c0714610a23578063d547741f14610a43578063dd62ed3e14610a6357600080fd5b8063b3c20ebd116100d1578063b3c20ebd146109a2578063b3c6e9ee146109c4578063bc063e1a146109da578063bd82394314610a0357600080fd5b8063a457c2d714610942578063a9059cbb14610962578063adf186931461098257600080fd5b80638e3166bc1161016457806395d89b411161013e57806395d89b411461085c57806398c47e8c146108715780639b61f1d01461090c578063a217fddf1461092d57600080fd5b80638e3166bc146107d257806391d148541461080657806394b8a7031461082657600080fd5b80636f741f2a1461070357806370a082311461073c57806372bc55831461075c57806379cc67901461077c5780637a8baf521461079c5780637f5bbb2c146107b257600080fd5b8063282c51f31161026a578063395093511161022357806342966c68116101fd57806342966c681461066a5780634569c4451461068a578063490e5147146106aa5780634fbee193146106ca57600080fd5b8063395093511461060a5780633b90b9bf1461062a578063412736571461064a57600080fd5b8063282c51f3146105185780632f2ff15d1461054c578063313ce5671461056c5780633502628a146105aa57806336568abe146105ca5780633935ebf9146105ea57600080fd5b806312363f4a116102d757806323b872dd116102b157806323b872dd14610470578063248a9ca31461049057806326991cc8146104c0578063269f534c146104f857600080fd5b806312363f4a1461040757806318160ddd1461043b5780631fa67b4d1461045057600080fd5b806301a6c43b1461032a57806301ffc9a71461035357806306fdde0314610383578063095ea7b3146103a55780630a4e42ef146103c55780630f569dad146103e757600080fd5b3661032557005b600080fd5b34801561033657600080fd5b50610340600e5481565b6040519081526020015b60405180910390f35b34801561035f57600080fd5b5061037361036e366004612e73565b610aef565b604051901515815260200161034a565b34801561038f57600080fd5b50610398610b26565b60405161034a9190612ec1565b3480156103b157600080fd5b506103736103c0366004612f09565b610bb8565b3480156103d157600080fd5b506103e56103e0366004612f35565b610bd0565b005b3480156103f357600080fd5b506103e5610402366004612f57565b610c46565b34801561041357600080fd5b506103407f000000000000000000000000000000312f313639393932342f412f422f572f5481565b34801561044757600080fd5b50600254610340565b34801561045c57600080fd5b506103e561046b366004612f70565b610c64565b34801561047c57600080fd5b5061037361048b366004612f8d565b610c89565b34801561049c57600080fd5b506103406104ab366004612f57565b60009081526006602052604090206001015490565b3480156104cc57600080fd5b50600c546104e0906001600160a01b031681565b6040516001600160a01b03909116815260200161034a565b34801561050457600080fd5b50610373610513366004612f70565b610cad565b34801561052457600080fd5b506103407f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84881565b34801561055857600080fd5b506103e5610567366004612fce565b610cd9565b34801561057857600080fd5b5060405160ff7f000000000000000000000000000000000000000000000000000000000000001216815260200161034a565b3480156105b657600080fd5b506103e56105c5366004612f09565b610cfe565b3480156105d657600080fd5b506103e56105e5366004612fce565b610d20565b3480156105f657600080fd5b50600d546104e0906001600160a01b031681565b34801561061657600080fd5b50610373610625366004612f09565b610d9a565b34801561063657600080fd5b50610373610645366004612f70565b610dbc565b34801561065657600080fd5b506103e5610665366004612f70565b610dc9565b34801561067657600080fd5b506103e5610685366004612f57565b610dea565b34801561069657600080fd5b506103e56106a5366004613013565b610e1e565b3480156106b657600080fd5b506103e56106c536600461303f565b610ee3565b3480156106d657600080fd5b506103736106e5366004612f70565b6001600160a01b031660009081526010602052604090205460ff1690565b34801561070f57600080fd5b5061037361071e366004612f70565b6001600160a01b031660009081526011602052604090205460ff1690565b34801561074857600080fd5b50610340610757366004612f70565b610f12565b34801561076857600080fd5b506103e5610777366004612f70565b610f2d565b34801561078857600080fd5b506103e5610797366004612f09565b610f68565b3480156107a857600080fd5b5061034060055481565b3480156107be57600080fd5b506103e56107cd366004613057565b610f9c565b3480156107de57600080fd5b506103407f5df7ebf31955a926cc63dac31c1a31bc588cdae5c3e13e63b89ebfe0eaba875381565b34801561081257600080fd5b50610373610821366004612fce565b611005565b34801561083257600080fd5b50610340610841366004612f70565b6001600160a01b031660009081526009602052604090205490565b34801561086857600080fd5b50610398611030565b34801561087d57600080fd5b50600f546108ca9060ff81169061ffff610100820481169163010000008104821691650100000000008204811691600160381b8104821691600160481b8204811691600160581b90041687565b60408051971515885261ffff968716602089015294861694870194909452918416606086015283166080850152821660a08401521660c082015260e00161034a565b34801561091857600080fd5b50600d5461037390600160a81b900460ff1681565b34801561093957600080fd5b50610340600081565b34801561094e57600080fd5b5061037361095d366004612f09565b61103f565b34801561096e57600080fd5b5061037361097d366004612f09565b6110ba565b34801561098e57600080fd5b506103e561099d366004613072565b6110c8565b3480156109ae57600080fd5b5061034060008051602061344483398151915281565b3480156109d057600080fd5b50610340600a5481565b3480156109e657600080fd5b506109f06107d081565b60405161ffff909116815260200161034a565b348015610a0f57600080fd5b506103e5610a1e366004612f57565b6110ea565b348015610a2f57600080fd5b50600b546104e0906001600160a01b031681565b348015610a4f57600080fd5b506103e5610a5e366004612fce565b6110fe565b348015610a6f57600080fd5b50610340610a7e36600461309e565b611123565b348015610a8f57600080fd5b506103e5610a9e366004613072565b61114e565b348015610aaf57600080fd5b506109f061271081565b348015610ac557600080fd5b506103e5610ad4366004612f09565b611170565b348015610ae557600080fd5b506104e061dead81565b60006001600160e01b03198216637965db0b60e01b1480610b2057506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060038054610b35906130cc565b80601f0160208091040260200160405190810160405280929190818152602001828054610b61906130cc565b8015610bae5780601f10610b8357610100808354040283529160200191610bae565b820191906000526020600020905b815481529060010190602001808311610b9157829003601f168201915b5050505050905090565b600033610bc6818585611192565b5060019392505050565b600080516020613444833981519152610be8816112b6565b610bf130610f12565b831115610c375760405162461bcd60e51b815260206004820152600f60248201526e082dadeeadce840e8dede40d0d2ced608b1b60448201526064015b60405180910390fd5b610c4183836112c3565b505050565b600080516020613444833981519152610c5e816112b6565b50600e55565b600080516020613444833981519152610c7c816112b6565b610c8582611425565b5050565b600033610c978582856114f1565b610ca2858585611565565b506001949350505050565b6000610b207f5df7ebf31955a926cc63dac31c1a31bc588cdae5c3e13e63b89ebfe0eaba875383611005565b600082815260066020526040902060010154610cf4816112b6565b610c418383611570565b600080516020613444833981519152610d16816112b6565b610c4183836115f6565b6001600160a01b0381163314610d905760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610c2e565b610c858282611707565b600033610bc6818585610dad8383611123565b610db79190613116565b611192565b6000610b2060078361176e565b600080516020613444833981519152610de1816112b6565b610c8582611793565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848610e14816112b6565b610c853383611ad0565b600080516020613444833981519152610e36816112b6565b8115610e8e5782610e4630610f12565b1015610e895760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606401610c2e565b610ed3565b82471015610ed35760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606401610c2e565b610edd8383611c0e565b50505050565b600080516020613444833981519152610efb816112b6565b610c85610f0d36849003840184613151565b611d6d565b6001600160a01b031660009081526020819052604090205490565b600080516020613444833981519152610f45816112b6565b50600d80546001600160a01b0319166001600160a01b0392909216919091179055565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848610f92816112b6565b610c418383612046565b600080516020613444833981519152610fb4816112b6565b811515600d60159054906101000a900460ff16151503610fe65760405162461bcd60e51b8152600401610c2e9061320f565b50600d8054911515600160a81b0260ff60a81b19909216919091179055565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b606060048054610b35906130cc565b6000338161104d8286611123565b9050838110156110ad5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610c2e565b610ca28286868403611192565b600033610bc6818585611565565b6000805160206134448339815191526110e0816112b6565b610c4183836120d0565b60006110f5816112b6565b610c8582612168565b600082815260066020526040902060010154611119816112b6565b610c418383611707565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600080516020613444833981519152611166816112b6565b610c41838361220c565b600080516020613444833981519152611188816112b6565b610c4183836122a4565b6001600160a01b0383166111f45760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c2e565b6001600160a01b0382166112555760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c2e565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6112c081336123db565b50565b600d805460ff60a01b1916600160a01b17905560006112e130610f12565b905082811061141257600f5460009061130790600160381b900461ffff16612710613234565b600f5461ffff9182169161132391600160481b9004168661324f565b61132d9190613266565b9050600061133c600283613266565b9050600061134a8387613288565b905060006113588385613288565b600f5490915060ff166113725761136f8282613116565b90505b80156113e457600c5461138d906001600160a01b0316610f12565b60000361139e575050505050611414565b476113a98288612434565b60006113b58247613288565b90506000836113c4878461324f565b6113ce9190613266565b905080156113e0576113e0868261258e565b5050505b600f5460ff1615611400576113fa826001611c0e565b5061140d565b61140b476000611c0e565b505b505050505b505b5050600d805460ff60a01b19169055565b61143060078261176e565b6114705760405162461bcd60e51b81526020600482015260116024820152702737ba103332b29031b7b63632b1ba37b960791b6044820152606401610c2e565b61147b600782612642565b506001600160a01b038116600090815260096020526040812054600a8054919290916114a8908490613288565b90915550506001600160a01b038116600081815260096020526040808220829055517f904316769e154356a5e4aad5d41591b55913c7717fab281d818c1fed7d80e8149190a250565b60006114fd8484611123565b90506000198114610edd57818110156115585760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610c2e565b610edd8484848403611192565b610c41838383612657565b61157a8282611005565b610c855760008281526006602090815260408083206001600160a01b03851684529091529020805460ff191660011790556115b23390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61160160078361176e565b156116465760405162461bcd60e51b815260206004820152601560248201527420b63932b0b23c903332b29031b7b63632b1ba37b960591b6044820152606401610c2e565b600081116116865760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b6044820152606401610c2e565b6116916007836128ea565b506001600160a01b0382166000908152600960205260408120829055600a80548392906116bf908490613116565b90915550506040518181526001600160a01b038316907f918584c21fe4a093f5014c0dabaed3e43b642781e27984aef122cae8245fbb23906020015b60405180910390a25050565b6117118282611005565b15610c855760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6001600160a01b0381166117da5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b2103937baba32b960911b6044820152606401610c2e565b600b80546001600160a01b0319166001600160a01b0383169081179091556040805163c45a015560e01b815290516000929163c45a01559160048083019260209291908290030181865afa158015611836573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185a919061329b565b90506001600160a01b0381166118a45760405162461bcd60e51b815260206004820152600f60248201526e496e76616c696420666163746f727960881b6044820152606401610c2e565b600b54604080516315ab88c960e31b815290516000926001600160a01b03169163ad5c46489160048083019260209291908290030181865afa1580156118ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611912919061329b565b60405163e6a4390560e01b81523060048201526001600160a01b0380831660248301529192509083169063e6a4390590604401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611986919061329b565b600c80546001600160a01b0319166001600160a01b03929092169182179055611a3c576040516364e329cb60e11b81523060048201526001600160a01b03828116602483015283169063c9c65396906044016020604051808303816000875af11580156119f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1b919061329b565b600c80546001600160a01b0319166001600160a01b03929092169190911790555b600c546001600160a01b0316611a8c5760405162461bcd60e51b815260206004820152601560248201527424b73b30b634b2103830b4b91030b2323932b9b99760591b6044820152606401610c2e565b600c54600b546040516001600160a01b0392831692909116907fca394f95d8dbf1e8b2e76b9a8da90cacce1da85181a65508dab13212dc1df53b90600090a3505050565b6001600160a01b038216611b305760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c2e565b611b3c826000836128ff565b6001600160a01b03821660009081526020819052604090205481811015611bb05760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610c2e565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b600082600003611c2057506000610b20565b600a54600003611c3257506000610b20565b600080611c3f600761290a565b905060005b81811015611d61576000611c59600783612914565b90506000611c68600185613288565b8314611ca357600a546001600160a01b038316600090815260096020526040902054611c94908a61324f565b611c9e9190613266565b611cad565b611cad8589613288565b90508615611cc557611cc0308383611565565b611cfd565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611cfb573d6000803e3d6000fd5b505b816001600160a01b03167f06c5efeff5c320943d265dc4e5f1af95ad523555ce0c1957e367dda5514572df82604051611d3891815260200190565b60405180910390a2611d4a8186613116565b945050508080611d59906132b8565b915050611c44565b50600195945050505050565b6107d061ffff16816020015161ffff161115611dbd5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206275792066656560881b6044820152606401610c2e565b6107d061ffff16816040015161ffff161115611e0e5760405162461bcd60e51b815260206004820152601060248201526f496e76616c69642073656c6c2066656560801b6044820152606401610c2e565b6107d061ffff16816060015161ffff161115611e635760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964207472616e736665722066656560601b6044820152606401610c2e565b60008160c001518260a001518360800151611e7e91906132d1565b611e8891906132d1565b905061ffff81161580611ea0575061ffff8116612710145b611ee05760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642066656520736861726560781b6044820152606401610c2e565b8151600f805460208501516040808701516060880151608089015160a08a015160c08b015161ffff908116600160581b0261ffff60581b19928216600160481b026affff00000000000000000019948316600160381b02949094166affffffff0000000000000019958316650100000000000266ffff0000000000199784166301000000029790971666ffffffff00000019939099166101000262ffff00199c15159c909c1662ffffff19909a16999099179a909a1716959095179290921716939093179290921716929092179055517ff34b49a91d91598b7774795175736ebf4db4fa5a4edf72772cf50fb27c135efd9061203a908490600060e082019050825115158252602083015161ffff80821660208501528060408601511660408501528060608601511660608501528060808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b60405180910390a15050565b60006120528333611123565b9050818110156120b95760405162461bcd60e51b815260206004820152602c60248201527f45524332304275726e61626c653a206275726e20616d6f756e7420657863656560448201526b647320616c6c6f77616e636560a01b6064820152608401610c2e565b6120c68333848403611192565b610c418383611ad0565b6001600160a01b03821660009081526010602052604090205481151560ff9091161515036121105760405162461bcd60e51b8152600401610c2e9061320f565b6001600160a01b038216600081815260106020908152604091829020805460ff191685151590811790915591519182527f3499bfcf9673677ba552f3fe2ea274ec7e6246da31c3c87e115b45a9b0db2efb91016116fb565b80158061219457506103e861217c60025490565b61218790600561324f565b6121919190613266565b81115b6121d15760405162461bcd60e51b815260206004820152600e60248201526d416d6f756e7420746f6f206c6f7760901b6044820152606401610c2e565b60058190556040518181527f0271c3ca991d8fa13fc3df55bfd888e9347a178a375ef6e0f63afa9639d144f49060200160405180910390a150565b6001600160a01b03821660009081526011602052604090205481151560ff90911615150361224c5760405162461bcd60e51b8152600401610c2e9061320f565b6001600160a01b038216600081815260116020908152604091829020805460ff191685151590811790915591519182527f902b2ea0acdec5a260e398590d055fe29bd61ef5dd41e45db54a4cd98d5569e091016116fb565b6122af60078361176e565b6122ef5760405162461bcd60e51b81526020600482015260116024820152702737ba103332b29031b7b63632b1ba37b960791b6044820152606401610c2e565b6000811161232f5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c696420736861726560981b6044820152606401610c2e565b6001600160a01b038216600090815260096020526040812054600a80549192839261235b908490613288565b90915550506001600160a01b0383166000908152600960205260408120839055600a805484929061238d908490613116565b909155505060408051828152602081018490526001600160a01b038516917fd350c3685bdab1285c0b97ffb6e96d96ed0ad4578a135c38250e771e7cb831aa910160405180910390a2505050565b6123e58282611005565b610c85576123f281612920565b6123fd836020612932565b60405160200161240e9291906132ec565b60408051601f198184030181529082905262461bcd60e51b8252610c2e91600401612ec1565b604080516002808252606082018352600092602083019080368337019050509050308160008151811061246957612469613361565b6001600160a01b03928316602091820292909201810191909152600b54604080516315ab88c960e31b81529051919093169263ad5c46489260048083019391928290030181865afa1580156124c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e6919061329b565b816001815181106124f9576124f9613361565b6001600160a01b039283166020918202929092010152600b5461251f9130911685611192565b600b5460405163791ac94760e01b81526001600160a01b039091169063791ac947906125579086908690869030904290600401613377565b600060405180830381600087803b15801561257157600080fd5b505af1158015612585573d6000803e3d6000fd5b50505050505050565b600b546125a69030906001600160a01b031684611192565b600b54600d5460405163f305d71960e01b81523060048201526024810185905260006044820181905260648201526001600160a01b0391821660848201524260a482015291169063f305d71990839060c40160606040518083038185885af1158015612616573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061263b91906133e8565b5050505050565b600061178c836001600160a01b038416612ace565b600081116126975760405162461bcd60e51b815260206004820152600d60248201526c05472616e73666572203c3d203609c1b6044820152606401610c2e565b600d546000908190600160a01b900460ff161580156126bf5750600d54600160a81b900460ff165b600d54909150600160a01b900460ff166127df576001600160a01b03858116600081815260106020908152604080832054948916808452818420549484526011909252808320549183529091205460ff93841693928316929182169116818015612727575080155b8015612731575082155b801561274b5750600b546001600160a01b03898116911614155b1561276357600f54610100900461ffff1695506127da565b80801561276e575083155b8015612778575082155b1561279257600f546301000000900461ffff1695506127da565b8115801561279e575080155b80156127b85750600b546001600160a01b038a8116911614155b80156127c2575083155b156127da57600f5465010000000000900461ffff1695505b505050505b8080156127ec5750600082115b801561281157506001600160a01b03851660009081526011602052604090205460ff16155b1561283b57600061282130610f12565b9050600e54811061283957612839600e5460006112c3565b505b81156128df576000612710612850848661324f565b61285a9190613266565b905060006128688286613288565b600f549091506000906127109061288a90600160381b900461ffff168561324f565b6128949190613266565b905080156128b5576128a68184613288565b92506128b58861dead83612bc8565b82156128c6576128c6883085612bc8565b81156128d7576128d7888884612bc8565b50505061263b565b61263b858585612bc8565b600061178c836001600160a01b038416612d77565b610c41838383612dc6565b6000610b20825490565b600061178c8383612e49565b6060610b206001600160a01b03831660145b6060600061294183600261324f565b61294c906002613116565b67ffffffffffffffff81111561296457612964613129565b6040519080825280601f01601f19166020018201604052801561298e576020820181803683370190505b509050600360fc1b816000815181106129a9576129a9613361565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106129d8576129d8613361565b60200101906001600160f81b031916908160001a90535060006129fc84600261324f565b612a07906001613116565b90505b6001811115612a7f576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612a3b57612a3b613361565b1a60f81b828281518110612a5157612a51613361565b60200101906001600160f81b031916908160001a90535060049490941c93612a7881613416565b9050612a0a565b50831561178c5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610c2e565b60008181526001830160205260408120548015612bb7576000612af2600183613288565b8554909150600090612b0690600190613288565b9050818114612b6b576000866000018281548110612b2657612b26613361565b9060005260206000200154905080876000018481548110612b4957612b49613361565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612b7c57612b7c61342d565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610b20565b6000915050610b20565b5092915050565b6001600160a01b038316612c2c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c2e565b6001600160a01b038216612c8e5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c2e565b612c998383836128ff565b6001600160a01b03831660009081526020819052604090205481811015612d115760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610c2e565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610edd565b6000818152600183016020526040812054612dbe57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610b20565b506000610b20565b828282600554600014158015612de25750612de082610cad565b155b15612e415760055481612df484610f12565b612dfe9190613116565b1115612e415760405162461bcd60e51b81526020600482015260126024820152710aec2d8d8cae840caf0c6cacac8e640dac2f60731b6044820152606401610c2e565b505050505050565b6000826000018281548110612e6057612e60613361565b9060005260206000200154905092915050565b600060208284031215612e8557600080fd5b81356001600160e01b03198116811461178c57600080fd5b60005b83811015612eb8578181015183820152602001612ea0565b50506000910152565b6020815260008251806020840152612ee0816040850160208701612e9d565b601f01601f19169190910160400192915050565b6001600160a01b03811681146112c057600080fd5b60008060408385031215612f1c57600080fd5b8235612f2781612ef4565b946020939093013593505050565b60008060408385031215612f4857600080fd5b50508035926020909101359150565b600060208284031215612f6957600080fd5b5035919050565b600060208284031215612f8257600080fd5b813561178c81612ef4565b600080600060608486031215612fa257600080fd5b8335612fad81612ef4565b92506020840135612fbd81612ef4565b929592945050506040919091013590565b60008060408385031215612fe157600080fd5b823591506020830135612ff381612ef4565b809150509250929050565b8035801515811461300e57600080fd5b919050565b6000806040838503121561302657600080fd5b8235915061303660208401612ffe565b90509250929050565b600060e0828403121561305157600080fd5b50919050565b60006020828403121561306957600080fd5b61178c82612ffe565b6000806040838503121561308557600080fd5b823561309081612ef4565b915061303660208401612ffe565b600080604083850312156130b157600080fd5b82356130bc81612ef4565b91506020830135612ff381612ef4565b600181811c908216806130e057607f821691505b60208210810361305157634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610b2057610b20613100565b634e487b7160e01b600052604160045260246000fd5b803561ffff8116811461300e57600080fd5b600060e0828403121561316357600080fd5b60405160e0810181811067ffffffffffffffff8211171561319457634e487b7160e01b600052604160045260246000fd5b6040526131a083612ffe565b81526131ae6020840161313f565b60208201526131bf6040840161313f565b60408201526131d06060840161313f565b60608201526131e16080840161313f565b60808201526131f260a0840161313f565b60a082015261320360c0840161313f565b60c08201529392505050565b6020808252600b908201526a105b1c9958591e481cd95d60aa1b604082015260600190565b61ffff828116828216039080821115612bc157612bc1613100565b8082028115828204841417610b2057610b20613100565b60008261328357634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610b2057610b20613100565b6000602082840312156132ad57600080fd5b815161178c81612ef4565b6000600182016132ca576132ca613100565b5060010190565b61ffff818116838216019080821115612bc157612bc1613100565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613324816017850160208801612e9d565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613355816028840160208801612e9d565b01602801949350505050565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156133c75784516001600160a01b0316835293830193918301916001016133a2565b50506001600160a01b03969096166060850152505050608001529392505050565b6000806000606084860312156133fd57600080fd5b8351925060208401519150604084015190509250925092565b60008161342557613425613100565b506000190190565b634e487b7160e01b600052603160045260246000fdfecaa508224cbc2c612b91345550b57fa87a9308bdc3d83a613f48278c1ef82485a2646970667358221220f4f556e7fa0da4ef89bb1c88f77c2cdf6e41fd7c1380b97cd9f5c0a094948e3864736f6c63430008130033

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

0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000000000000000000000000000eb2a9ee506c18566f826849b3c56deb7ff67d8050000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000028168a117d819d2bcfc3598031262767c4054ec000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000002710

-----Decoded View---------------
Arg [0] : initialSupply_ (uint256): 1000000000000000000000000000
Arg [1] : feeReceiver_ (address): 0xEb2A9EE506c18566F826849B3c56deb7Ff67D805
Arg [2] : swapRouter_ (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [3] : feeConfiguration_ (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [4] : collectors_ (address[]): 0x28168a117D819d2BCFC3598031262767C4054EC0
Arg [5] : shares_ (uint256[]): 10000

-----Encoded View---------------
16 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000
Arg [1] : 000000000000000000000000eb2a9ee506c18566f826849b3c56deb7ff67d805
Arg [2] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [6] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [7] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [8] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [9] : 0000000000000000000000000000000000000000000000000000000000001f40
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [11] : 00000000000000000000000000000000000000000000000000000000000001c0
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [13] : 00000000000000000000000028168a117d819d2bcfc3598031262767c4054ec0
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [15] : 0000000000000000000000000000000000000000000000000000000000002710


Deployed Bytecode Sourcemap

374:6268:14:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1568:30:19;;;;;;;;;;;;;;;;;;;160:25:20;;;148:2;133:18;1568:30:19;;;;;;;;2606:202:0;;;;;;;;;;-1:-1:-1;2606:202:0;;;;;:::i;:::-;;:::i;:::-;;;652:14:20;;645:22;627:41;;615:2;600:18;2606:202:0;487:187:20;2154:98:2;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4431:197::-;;;;;;;;;;-1:-1:-1;4431:197:2;;;;;:::i;:::-;;:::i;4709:225:14:-;;;;;;;;;;-1:-1:-1;4709:225:14;;;;;:::i;:::-;;:::i;:::-;;5547:128;;;;;;;;;;-1:-1:-1;5547:128:14;;;;;:::i;:::-;;:::i;197:35:16:-;;;;;;;;;;;;;;;3242:106:2;;;;;;;;;;-1:-1:-1;3329:12:2;;3242:106;;5047:133:14;;;;;;;;;;-1:-1:-1;5047:133:14;;;;;:::i;:::-;;:::i;5190:286:2:-;;;;;;;;;;-1:-1:-1;5190:286:2;;;;;:::i;:::-;;:::i;4378:129:0:-;;;;;;;;;;-1:-1:-1;4378:129:0;;;;;:::i;:::-;4452:7;4478:12;;;:6;:12;;;;;:22;;;;4378:129;1424:23:19;;;;;;;;;;-1:-1:-1;1424:23:19;;;;-1:-1:-1;;;;;1424:23:19;;;;;;-1:-1:-1;;;;;3473:32:20;;;3455:51;;3443:2;3428:18;1424:23:19;3309:203:20;2058:156:14;;;;;;;;;;-1:-1:-1;2058:156:14;;;;;:::i;:::-;;:::i;472:62::-;;;;;;;;;;;;510:24;472:62;;4803:145:0;;;;;;;;;;-1:-1:-1;4803:145:0;;;;;:::i;:::-;;:::i;471:90:16:-;;;;;;;;;;-1:-1:-1;471:90:16;;4009:4:20;545:9:16;3997:17:20;3979:36;;3967:2;3952:18;471:90:16;3837:184:20;3425:149:14;;;;;;;;;;-1:-1:-1;3425:149:14;;;;;:::i;:::-;;:::i;5912:214:0:-;;;;;;;;;;-1:-1:-1;5912:214:0;;;;;:::i;:::-;;:::i;1453:29:19:-;;;;;;;;;;-1:-1:-1;1453:29:19;;;;-1:-1:-1;;;;;1453:29:19;;;5871:234:2;;;;;;;;;;-1:-1:-1;5871:234:2;;;;;:::i;:::-;;:::i;977:121:18:-;;;;;;;;;;-1:-1:-1;977:121:18;;;;;:::i;:::-;;:::i;6357:127:14:-;;;;;;;;;;-1:-1:-1;6357:127:14;;;;;:::i;:::-;;:::i;2343:114::-;;;;;;;;;;-1:-1:-1;2343:114:14;;;;;:::i;:::-;;:::i;4255:351::-;;;;;;;;;;-1:-1:-1;4255:351:14;;;;;:::i;:::-;;:::i;6079:165::-;;;;;;;;;;-1:-1:-1;6079:165:14;;;;;:::i;:::-;;:::i;3051:122:19:-;;;;;;;;;;-1:-1:-1;3051:122:19;;;;;:::i;:::-;-1:-1:-1;;;;;3140:26:19;3117:4;3140:26;;;:17;:26;;;;;;;;;3051:122;3654:111;;;;;;;;;;-1:-1:-1;3654:111:19;;;;;:::i;:::-;-1:-1:-1;;;;;3737:21:19;3714:4;3737:21;;;:8;:21;;;;;;;;;3654:111;3406:125:2;;;;;;;;;;-1:-1:-1;3406:125:2;;;;;:::i;:::-;;:::i;5294:130:14:-;;;;;;;;;;-1:-1:-1;5294:130:14;;;;;:::i;:::-;;:::i;2631:134::-;;;;;;;;;;-1:-1:-1;2631:134:14;;;;;:::i;:::-;;:::i;189:32:15:-;;;;;;;;;;;;;;;;3116:199:14;;;;;;;;;;-1:-1:-1;3116:199:14;;;;;:::i;:::-;;:::i;540:96::-;;;;;;;;;;;;595:41;540:96;;2895:145:0;;;;;;;;;;-1:-1:-1;2895:145:0;;;;;:::i;:::-;;:::i;1104:114:18:-;;;;;;;;;;-1:-1:-1;1104:114:18;;;;;:::i;:::-;-1:-1:-1;;;;;1195:16:18;1169:7;1195:16;;;:7;:16;;;;;;;1104:114;2365:102:2;;;;;;;;;;;;;:::i;1687:40:19:-;;;;;;;;;;-1:-1:-1;1687:40:19;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1687:40:19;;;;;-1:-1:-1;;;1687:40:19;;;;;-1:-1:-1;;;1687:40:19;;;;;;;;;5159:14:20;;5152:22;5134:41;;5194:6;5236:15;;;5231:2;5216:18;;5209:43;5288:15;;;5268:18;;;5261:43;;;;5340:15;;;5335:2;5320:18;;5313:43;5393:15;;5387:3;5372:19;;5365:44;5446:15;;5440:3;5425:19;;5418:44;5499:15;5493:3;5478:19;;5471:44;5121:3;5106:19;1687:40:19;4837:684:20;1535:27:19;;;;;;;;;;-1:-1:-1;1535:27:19;;;;-1:-1:-1;;;1535:27:19;;;;;;2027:49:0;;;;;;;;;;-1:-1:-1;2027:49:0;2072:4;2027:49;;6592:427:2;;;;;;;;;;-1:-1:-1;6592:427:2;;;;;:::i;:::-;;:::i;3727:189::-;;;;;;;;;;-1:-1:-1;3727:189:2;;;;;:::i;:::-;;:::i;3962:164:14:-;;;;;;;;;;-1:-1:-1;3962:164:14;;;;;:::i;:::-;;:::i;642:68::-;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;642:68:14;;358:39:18;;;;;;;;;;;;;;;;1253:37:19;;;;;;;;;;;;1286:4;1253:37;;;;;6020:6:20;6008:19;;;5990:38;;5978:2;5963:18;1253:37:19;5846:188:20;1842:130:14;;;;;;;;;;-1:-1:-1;1842:130:14;;;;;:::i;:::-;;:::i;1382:36:19:-;;;;;;;;;;-1:-1:-1;1382:36:19;;;;-1:-1:-1;;;;;1382:36:19;;;5228:147:0;;;;;;;;;;-1:-1:-1;5228:147:0;;;;;:::i;:::-;;:::i;3974:149:2:-;;;;;;;;;;-1:-1:-1;3974:149:2;;;;;:::i;:::-;;:::i;3680:144:14:-;;;;;;;;;;-1:-1:-1;3680:144:14;;;;;:::i;:::-;;:::i;1312:44:19:-;;;;;;;;;;;;1351:5;1312:44;;5794:165:14;;;;;;;;;;-1:-1:-1;5794:165:14;;;;;:::i;:::-;;:::i;1157:90:19:-;;;;;;;;;;;;1204:42;1157:90;;2606:202:0;2691:4;-1:-1:-1;;;;;;2714:47:0;;-1:-1:-1;;;2714:47:0;;:87;;-1:-1:-1;;;;;;;;;;937:40:7;;;2765:36:0;2707:94;2606:202;-1:-1:-1;;2606:202:0:o;2154:98:2:-;2208:13;2240:5;2233:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2154:98;:::o;4431:197::-;4514:4;719:10:5;4568:32:2;719:10:5;4584:7:2;4593:6;4568:8;:32::i;:::-;-1:-1:-1;4617:4:2;;4431:197;-1:-1:-1;;;4431:197:2:o;4709:225:14:-;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;4839:24:14::1;4857:4;4839:9;:24::i;:::-;4829:6;:34;;4821:62;;;::::0;-1:-1:-1;;;4821:62:14;;7254:2:20;4821:62:14::1;::::0;::::1;7236:21:20::0;7293:2;7273:18;;;7266:30;-1:-1:-1;;;7312:18:20;;;7305:45;7367:18;;4821:62:14::1;;;;;;;;;4893:34;4906:6;4914:12;4893;:34::i;:::-;4709:225:::0;;;:::o;5547:128::-;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;-1:-1:-1;5644:15:14::1;:24:::0;5547:128::o;5047:133::-;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;5145:28:14::1;5165:7;5145:19;:28::i;:::-;5047:133:::0;;:::o;5190:286:2:-;5317:4;719:10:5;5373:38:2;5389:4;719:10:5;5404:6:2;5373:15;:38::i;:::-;5421:27;5431:4;5437:2;5441:6;5421:9;:27::i;:::-;-1:-1:-1;5465:4:2;;5190:286;-1:-1:-1;;;;5190:286:2:o;2058:156:14:-;2138:4;2161:46;595:41;2199:7;2161;:46::i;4803:145:0:-;4452:7;4478:12;;;:6;:12;;;;;:22;;;2505:16;2516:4;2505:10;:16::i;:::-;4916:25:::1;4927:4;4933:7;4916:10;:25::i;3425:149:14:-:0;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;3535:32:14::1;3552:7;3561:5;3535:16;:32::i;5912:214:0:-:0;-1:-1:-1;;;;;6007:23:0;;719:10:5;6007:23:0;5999:83;;;;-1:-1:-1;;;5999:83:0;;7598:2:20;5999:83:0;;;7580:21:20;7637:2;7617:18;;;7610:30;7676:34;7656:18;;;7649:62;-1:-1:-1;;;7727:18:20;;;7720:45;7782:19;;5999:83:0;7396:411:20;5999:83:0;6093:26;6105:4;6111:7;6093:11;:26::i;5871:234:2:-;5959:4;719:10:5;6013:64:2;719:10:5;6029:7:2;6066:10;6038:25;719:10:5;6029:7:2;6038:9;:25::i;:::-;:38;;;;:::i;:::-;6013:8;:64::i;977:121:18:-;1039:4;1062:29;:11;1083:7;1062:20;:29::i;6357:127:14:-;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;6452:25:14::1;6467:9;6452:14;:25::i;2343:114::-:0;510:24;2505:16:0;2516:4;2505:10;:16::i;:::-;2423:27:14::1;719:10:5::0;2443:6:14::1;2423:5;:27::i;4255:351::-:0;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;4366:7:14::1;4362:196;;;4425:6;4397:24;4415:4;4397:9;:24::i;:::-;:34;;4389:65;;;::::0;-1:-1:-1;;;4389:65:14;;8276:2:20;4389:65:14::1;::::0;::::1;8258:21:20::0;8315:2;8295:18;;;8288:30;-1:-1:-1;;;8334:18:20;;;8327:48;8392:18;;4389:65:14::1;8074:342:20::0;4389:65:14::1;4362:196;;;4518:6;4493:21;:31;;4485:62;;;::::0;-1:-1:-1;;;4485:62:14;;8276:2:20;4485:62:14::1;::::0;::::1;8258:21:20::0;8315:2;8295:18;;;8288:30;-1:-1:-1;;;8334:18:20;;;8327:48;8392:18;;4485:62:14::1;8074:342:20::0;4485:62:14::1;4567:32;4583:6;4591:7;4567:15;:32::i;:::-;;4255:351:::0;;;:::o;6079:165::-;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;6202:35:14::1;;;::::0;;::::1;::::0;::::1;6223:13:::0;6202:35:::1;:::i;:::-;:20;:35::i;3406:125:2:-:0;-1:-1:-1;;;;;3506:18:2;3480:7;3506:18;;;;;;;;;;;;3406:125::o;5294:130:14:-;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;-1:-1:-1;5392:14:14::1;:25:::0;;-1:-1:-1;;;;;;5392:25:14::1;-1:-1:-1::0;;;;;5392:25:14;;;::::1;::::0;;;::::1;::::0;;5294:130::o;2631:134::-;510:24;2505:16:0;2516:4;2505:10;:16::i;:::-;2732:26:14::1;2742:7;2751:6;2732:9;:26::i;3116:199::-:0;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;3242:11:14::1;3223:30;;:15;;;;;;;;;;;:30;;::::0;3215:54:::1;;;;-1:-1:-1::0;;;3215:54:14::1;;;;;;;:::i;:::-;-1:-1:-1::0;3279:15:14::1;:29:::0;;;::::1;;-1:-1:-1::0;;;3279:29:14::1;-1:-1:-1::0;;;;3279:29:14;;::::1;::::0;;;::::1;::::0;;3116:199::o;2895:145:0:-;2981:4;3004:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;3004:29:0;;;;;;;;;;;;;;;2895:145::o;2365:102:2:-;2421:13;2453:7;2446:14;;;;;:::i;6592:427::-;6685:4;719:10:5;6685:4:2;6766:25;719:10:5;6783:7:2;6766:9;:25::i;:::-;6739:52;;6829:15;6809:16;:35;;6801:85;;;;-1:-1:-1;;;6801:85:2;;10245:2:20;6801:85:2;;;10227:21:20;10284:2;10264:18;;;10257:30;10323:34;10303:18;;;10296:62;-1:-1:-1;;;10374:18:20;;;10367:35;10419:19;;6801:85:2;10043:401:20;6801:85:2;6920:60;6929:5;6936:7;6964:15;6945:16;:34;6920:8;:60::i;3727:189::-;3806:4;719:10:5;3860:28:2;719:10:5;3877:2:2;3881:6;3860:9;:28::i;3962:164:14:-;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;4078:41:14::1;4101:7;4110:8;4078:22;:41::i;1842:130::-:0;2072:4:0;2505:16;2072:4;2505:10;:16::i;:::-;1936:29:14::1;1958:6;1936:21;:29::i;5228:147:0:-:0;4452:7;4478:12;;;:6;:12;;;;;:22;;;2505:16;2516:4;2505:10;:16::i;:::-;5342:26:::1;5354:4;5360:7;5342:11;:26::i;3974:149:2:-:0;-1:-1:-1;;;;;4089:18:2;;;4063:7;4089:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3974:149::o;3680:144:14:-;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;3786:31:14::1;3799:11;3812:4;3786:12;:31::i;5794:165::-:0;-1:-1:-1;;;;;;;;;;;2505:16:0;2516:4;2505:10;:16::i;:::-;5912:40:14::1;5937:7;5946:5;5912:24;:40::i;10504:370:2:-:0;-1:-1:-1;;;;;10635:19:2;;10627:68;;;;-1:-1:-1;;;10627:68:2;;10651:2:20;10627:68:2;;;10633:21:20;10690:2;10670:18;;;10663:30;10729:34;10709:18;;;10702:62;-1:-1:-1;;;10780:18:20;;;10773:34;10824:19;;10627:68:2;10449:400:20;10627:68:2;-1:-1:-1;;;;;10713:21:2;;10705:68;;;;-1:-1:-1;;;10705:68:2;;11056:2:20;10705:68:2;;;11038:21:20;11095:2;11075:18;;;11068:30;11134:34;11114:18;;;11107:62;-1:-1:-1;;;11185:18:20;;;11178:32;11227:19;;10705:68:2;10854:398:20;10705:68:2;-1:-1:-1;;;;;10784:18:2;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;10835:32;;160:25:20;;;10835:32:2;;133:18:20;10835:32:2;;;;;;;10504:370;;;:::o;3334:103:0:-;3400:30;3411:4;719:10:5;3400::0;:30::i;:::-;3334:103;:::o;5084:1803:19:-;2143:15;:22;;-1:-1:-1;;;;2143:22:19;-1:-1:-1;;;2143:22:19;;;;5211:24:::1;5229:4;5211:9;:24::i;:::-;5180:55;;5273:11;5249:20;:35;5245:1636;;5412:16;:29:::0;5300:23:::1;::::0;5396:45:::1;::::0;-1:-1:-1;;;5412:29:19;::::1;;;1351:5;5396:45;:::i;:::-;5341:16;:34:::0;5326:116:::1;::::0;;::::1;::::0;5327:48:::1;::::0;-1:-1:-1;;;5341:34:19;::::1;;5327:11:::0;:48:::1;:::i;:::-;5326:116;;;;:::i;:::-;5300:142:::0;-1:-1:-1;5456:23:19::1;5482:19;5500:1;5300:142:::0;5482:19:::1;:::i;:::-;5456:45:::0;-1:-1:-1;5516:24:19::1;5543:29;5557:15:::0;5543:11;:29:::1;:::i;:::-;5516:56:::0;-1:-1:-1;5586:21:19::1;5610:33;5628:15:::0;5610;:33:::1;:::i;:::-;5663:16;:28:::0;5586:57;;-1:-1:-1;5663:28:19::1;;5658:101;;5711:33;5728:16:::0;5711:33;::::1;:::i;:::-;;;5658:101;5804:17:::0;;5800:762:::1;;5855:8;::::0;5845:19:::1;::::0;-1:-1:-1;;;;;5855:8:19::1;5845:9;:19::i;:::-;5868:1;5845:24:::0;5841:142:::1;;5958:7;;;;;;;5841:142;6085:21;6125:46;6143:13:::0;6158:12;6125:17:::1;:46::i;:::-;6241:19;6263:38;6287:14:::0;6263:21:::1;:38;:::i;:::-;6241:60:::0;-1:-1:-1;6353:20:19::1;6410:13:::0;6377:29:::1;6391:15:::0;6241:60;6377:29:::1;:::i;:::-;6376:47;;;;:::i;:::-;6353:70:::0;-1:-1:-1;6445:16:19;;6441:107:::1;;6485:44;6499:15;6516:12;6485:13;:44::i;:::-;5823:739;;;5800:762;6580:16;:28:::0;::::1;;6576:295;;;6677:39;6693:16;6711:4;6677:15;:39::i;:::-;;6576:295;;;6811:45;6827:21;6850:5;6811:15;:45::i;:::-;;6576:295;5286:1595;;;;5245:1636;5170:1717;2175:1;-1:-1:-1::0;;2186:15:19;:23;;-1:-1:-1;;;;2186:23:19;;;5084:1803::o;1584:299:18:-;1657:29;:11;1678:7;1657:20;:29::i;:::-;1649:59;;;;-1:-1:-1;;;1649:59:18;;12163:2:20;1649:59:18;;;12145:21:20;12202:2;12182:18;;;12175:30;-1:-1:-1;;;12221:18:20;;;12214:47;12278:18;;1649:59:18;11961:341:20;1649:59:18;1718:27;:11;1737:7;1718:18;:27::i;:::-;-1:-1:-1;;;;;;1783:16:18;;;;;;:7;:16;;;;;;1755:24;:44;;1783:16;;1755:24;;:44;;1783:16;;1755:44;:::i;:::-;;;;-1:-1:-1;;;;;;;1816:16:18;;;;;;:7;:16;;;;;;1809:23;;;1848:28;;;1816:16;1848:28;1584:299;:::o;11155:441:2:-;11285:24;11312:25;11322:5;11329:7;11312:9;:25::i;:::-;11285:52;;-1:-1:-1;;11351:16:2;:37;11347:243;;11432:6;11412:16;:26;;11404:68;;;;-1:-1:-1;;;11404:68:2;;12509:2:20;11404:68:2;;;12491:21:20;12548:2;12528:18;;;12521:30;12587:31;12567:18;;;12560:59;12636:18;;11404:68:2;12307:353:20;11404:68:2;11514:51;11523:5;11530:7;11558:6;11539:16;:25;11514:8;:51::i;6490:150:14:-;6600:33;6616:4;6622:2;6626:6;6600:15;:33::i;7461:233:0:-;7544:22;7552:4;7558:7;7544;:22::i;:::-;7539:149;;7582:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;7582:29:0;;;;;;;;;:36;;-1:-1:-1;;7582:36:0;7614:4;7582:36;;;7664:12;719:10:5;;640:96;7664:12:0;-1:-1:-1;;;;;7637:40:0;7655:7;-1:-1:-1;;;;;7637:40:0;7649:4;7637:40;;;;;;;;;;7461:233;;:::o;1224:354:18:-;1310:29;:11;1331:7;1310:20;:29::i;:::-;1309:30;1301:64;;;;-1:-1:-1;;;1301:64:18;;12867:2:20;1301:64:18;;;12849:21:20;12906:2;12886:18;;;12879:30;-1:-1:-1;;;12925:18:20;;;12918:51;12986:18;;1301:64:18;12665:345:20;1301:64:18;1391:1;1383:5;:9;1375:35;;;;-1:-1:-1;;;1375:35:18;;13217:2:20;1375:35:18;;;13199:21:20;13256:2;13236:18;;;13229:30;-1:-1:-1;;;13275:18:20;;;13268:43;13328:18;;1375:35:18;13015:337:20;1375:35:18;1421:24;:11;1437:7;1421:15;:24::i;:::-;-1:-1:-1;;;;;;1455:16:18;;;;;;:7;:16;;;;;:24;;;1489;:33;;1474:5;;1455:16;1489:33;;1474:5;;1489:33;:::i;:::-;;;;-1:-1:-1;;1538:33:18;;160:25:20;;;-1:-1:-1;;;;;1538:33:18;;;;;148:2:20;133:18;1538:33:18;;;;;;;;1224:354;;:::o;7865:234:0:-;7948:22;7956:4;7962:7;7948;:22::i;:::-;7944:149;;;8018:5;7986:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;7986:29:0;;;;;;;;;;:37;;-1:-1:-1;;7986:37:0;;;8042:40;719:10:5;;7986:12:0;;8042:40;;8018:5;8042:40;7865:234;;:::o;8852:165:10:-;-1:-1:-1;;;;;8985:23:10;;8932:4;4343:19;;;:12;;;:19;;;;;;:24;;8955:55;8948:62;8852:165;-1:-1:-1;;;8852:165:10:o;3771:662:19:-;-1:-1:-1;;;;;3842:24:19;;3834:51;;;;-1:-1:-1;;;3834:51:19;;13559:2:20;3834:51:19;;;13541:21:20;13598:2;13578:18;;;13571:30;-1:-1:-1;;;13617:18:20;;;13610:44;13671:18;;3834:51:19;13357:338:20;3834:51:19;3896:10;:43;;-1:-1:-1;;;;;;3896:43:19;-1:-1:-1;;;;;3896:43:19;;;;;;;;3995:20;;;-1:-1:-1;;;3995:20:19;;;;-1:-1:-1;;3896:43:19;3995:18;;:20;;;;;;;;;;;;;;3896:43;3995:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3949:67;-1:-1:-1;;;;;;4034:30:19;;4026:58;;;;-1:-1:-1;;;4026:58:19;;14158:2:20;4026:58:19;;;14140:21:20;14197:2;14177:18;;;14170:30;-1:-1:-1;;;14216:18:20;;;14209:45;14271:18;;4026:58:19;13956:339:20;4026:58:19;4110:10;;:17;;;-1:-1:-1;;;4110:17:19;;;;4095:12;;-1:-1:-1;;;;;4110:10:19;;:15;;:17;;;;;;;;;;;;;;:10;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4148:36;;-1:-1:-1;;;4148:36:19;;4172:4;4148:36;;;14512:34:20;-1:-1:-1;;;;;14582:15:20;;;14562:18;;;14555:43;4095:32:19;;-1:-1:-1;4148:15:19;;;;;;14447:18:20;;4148:36:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4137:8;:47;;-1:-1:-1;;;;;;4137:47:19;-1:-1:-1;;;;;4137:47:19;;;;;;;;;4194:103;;4247:39;;-1:-1:-1;;;4247:39:19;;4274:4;4247:39;;;14512:34:20;-1:-1:-1;;;;;14582:15:20;;;14562:18;;;14555:43;4247:18:19;;;;;14447::20;;4247:39:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4236:8;:50;;-1:-1:-1;;;;;;4236:50:19;-1:-1:-1;;;;;4236:50:19;;;;;;;;;;4194:103;4315:8;;-1:-1:-1;;;;;4315:8:19;4307:56;;;;-1:-1:-1;;;4307:56:19;;14811:2:20;4307:56:19;;;14793:21:20;14850:2;14830:18;;;14823:30;-1:-1:-1;;;14869:18:20;;;14862:51;14930:18;;4307:56:19;14609:345:20;4307:56:19;4417:8;;4404:10;;4378:48;;-1:-1:-1;;;;;4417:8:19;;;;4404:10;;;;4378:48;;4417:8;;4378:48;3824:609;;3771:662;:::o;9422:659:2:-;-1:-1:-1;;;;;9505:21:2;;9497:67;;;;-1:-1:-1;;;9497:67:2;;15161:2:20;9497:67:2;;;15143:21:20;15200:2;15180:18;;;15173:30;15239:34;15219:18;;;15212:62;-1:-1:-1;;;15290:18:20;;;15283:31;15331:19;;9497:67:2;14959:397:20;9497:67:2;9575:49;9596:7;9613:1;9617:6;9575:20;:49::i;:::-;-1:-1:-1;;;;;9660:18:2;;9635:22;9660:18;;;;;;;;;;;9696:24;;;;9688:71;;;;-1:-1:-1;;;9688:71:2;;15563:2:20;9688:71:2;;;15545:21:20;15602:2;15582:18;;;15575:30;15641:34;15621:18;;;15614:62;-1:-1:-1;;;15692:18:20;;;15685:32;15734:19;;9688:71:2;15361:398:20;9688:71:2;-1:-1:-1;;;;;9793:18:2;;:9;:18;;;;;;;;;;;9814:23;;;9793:44;;9930:12;:22;;;;;;;9978:37;160:25:20;;;9793:9:2;;:18;9978:37;;133:18:20;9978:37:2;;;;;;;4709:225:14;;;:::o;2322:802:18:-;2395:4;2415:6;2425:1;2415:11;2411:29;;-1:-1:-1;2435:5:18;2428:12;;2411:29;2454:24;;2482:1;2454:29;2450:47;;-1:-1:-1;2492:5:18;2485:12;;2450:47;2508:19;2541:11;2555:20;:11;:18;:20::i;:::-;2541:34;;2590:9;2585:511;2609:3;2605:1;:7;2585:511;;;2633:17;2653;:11;2668:1;2653:14;:17::i;:::-;2633:37;-1:-1:-1;2684:13:18;2705:7;2711:1;2705:3;:7;:::i;:::-;2700:1;:12;:126;;2802:24;;-1:-1:-1;;;;;2780:18:18;;;;;;:7;:18;;;;;;2771:27;;:6;:27;:::i;:::-;2770:56;;;;:::i;:::-;2700:126;;;2731:20;2740:11;2731:6;:20;:::i;:::-;2684:142;;2845:7;2841:161;;;2872:42;2890:4;2897:9;2908:5;2872:9;:42::i;:::-;2841:161;;;2953:34;;-1:-1:-1;;;;;2953:27:18;;;:34;;;;;2981:5;;2953:34;;;;2981:5;2953:27;:34;;;;;;;;;;;;;;;;;;;;;2841:161;3033:9;-1:-1:-1;;;;;3020:30:18;;3044:5;3020:30;;;;160:25:20;;148:2;133:18;;14:177;3020:30:18;;;;;;;;3065:20;3080:5;3065:20;;:::i;:::-;;;2619:477;;2614:3;;;;;:::i;:::-;;;;2585:511;;;-1:-1:-1;3113:4:18;;2322:802;-1:-1:-1;;;;;2322:802:18:o;4439:639:19:-;1286:4;4535:32;;:13;:21;;;:32;;;;4527:60;;;;-1:-1:-1;;;4527:60:19;;16106:2:20;4527:60:19;;;16088:21:20;16145:2;16125:18;;;16118:30;-1:-1:-1;;;16164:18:20;;;16157:45;16219:18;;4527:60:19;15904:339:20;4527:60:19;1286:4;4605:33;;:13;:22;;;:33;;;;4597:62;;;;-1:-1:-1;;;4597:62:19;;16450:2:20;4597:62:19;;;16432:21:20;16489:2;16469:18;;;16462:30;-1:-1:-1;;;16508:18:20;;;16501:46;16564:18;;4597:62:19;16248:340:20;4597:62:19;1286:4;4677:37;;:13;:26;;;:37;;;;4669:70;;;;-1:-1:-1;;;4669:70:19;;16795:2:20;4669:70:19;;;16777:21:20;16834:2;16814:18;;;16807:30;-1:-1:-1;;;16853:18:20;;;16846:50;16913:18;;4669:70:19;16593:344:20;4669:70:19;4750:17;4857:13;:32;;;4811:13;:31;;;4770:13;:26;;;:72;;;;:::i;:::-;:119;;;;:::i;:::-;4750:139;-1:-1:-1;4907:15:19;;;;;:46;;-1:-1:-1;4926:27:19;;;1351:5;4926:27;4907:46;4899:76;;;;-1:-1:-1;;;4899:76:19;;17317:2:20;4899:76:19;;;17299:21:20;17356:2;17336:18;;;17329:30;-1:-1:-1;;;17375:18:20;;;17368:47;17432:18;;4899:76:19;17115:341:20;4899:76:19;4986:32;;:16;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;4986:32:19;-1:-1:-1;;;;4986:32:19;;;-1:-1:-1;;;4986:32:19;-1:-1:-1;;4986:32:19;;;-1:-1:-1;;;4986:32:19;;;;;-1:-1:-1;;4986:32:19;;;;;-1:-1:-1;;4986:32:19;;;;;;;;;-1:-1:-1;;4986:32:19;;;;;;-1:-1:-1;;4986:32:19;;;;;;;-1:-1:-1;;4986:32:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5033:38;;;;;5005:13;;17621:4:20;17663:3;17652:9;17648:19;17640:27;;17714:6;17708:13;17701:21;17694:29;17683:9;17676:48;17771:4;17763:6;17759:17;17753:24;17796:6;17858:2;17844:12;17840:21;17833:4;17822:9;17818:20;17811:51;17930:2;17922:4;17914:6;17910:17;17904:24;17900:33;17893:4;17882:9;17878:20;17871:63;18002:2;17994:4;17986:6;17982:17;17976:24;17972:33;17965:4;17954:9;17950:20;17943:63;18074:2;18066:4;18058:6;18054:17;18048:24;18044:33;18037:4;18026:9;18022:20;18015:63;18146:2;18138:4;18130:6;18126:17;18120:24;18116:33;18109:4;18098:9;18094:20;18087:63;18218:2;18210:4;18202:6;18198:17;18192:24;18188:33;18181:4;18170:9;18166:20;18159:63;;;17461:767;;;;;5033:38:19;;;;;;;;4517:561;4439:639;:::o;906:372:17:-;985:24;1012:32;1022:7;719:10:5;3974:149:2;:::i;1012:32:17:-;985:59;;1082:6;1062:16;:26;;1054:83;;;;-1:-1:-1;;;1054:83:17;;18435:2:20;1054:83:17;;;18417:21:20;18474:2;18454:18;;;18447:30;18513:34;18493:18;;;18486:62;-1:-1:-1;;;18564:18:20;;;18557:42;18616:19;;1054:83:17;18233:408:20;1054:83:17;1171:58;1180:7;719:10:5;1222:6:17;1203:16;:25;1171:8;:58::i;:::-;1249:22;1255:7;1264:6;1249:5;:22::i;3179:249:19:-;-1:-1:-1;;;;;3270:26:19;;;;;;:17;:26;;;;;;:38;;;:26;;;;:38;;;3262:62;;;;-1:-1:-1;;;3262:62:19;;;;;;;:::i;:::-;-1:-1:-1;;;;;3334:26:19;;;;;;:17;:26;;;;;;;;;:37;;-1:-1:-1;;3334:37:19;;;;;;;;;;3386:35;;627:41:20;;;3386:35:19;;600:18:20;3386:35:19;487:187:20;928:256:15;1002:11;;;:50;;;1048:4;1027:13;3329:12:2;;;3242:106;1027:13:15;:17;;1043:1;1027:17;:::i;:::-;1026:26;;;;:::i;:::-;1017:6;:35;1002:50;994:77;;;;-1:-1:-1;;;994:77:15;;18848:2:20;994:77:15;;;18830:21:20;18887:2;18867:18;;;18860:30;-1:-1:-1;;;18906:18:20;;;18899:44;18960:18;;994:77:15;18646:338:20;994:77:15;1104:17;:26;;;1145:32;;160:25:20;;;1145:32:15;;148:2:20;133:18;1145:32:15;;;;;;;928:256;:::o;3434:214:19:-;-1:-1:-1;;;;;3515:21:19;;;;;;:8;:21;;;;;;:29;;;:21;;;;:29;;;3507:53;;;;-1:-1:-1;;;3507:53:19;;;;;;;:::i;:::-;-1:-1:-1;;;;;3570:21:19;;;;;;:8;:21;;;;;;;;;:28;;-1:-1:-1;;3570:28:19;;;;;;;;;;3613;;627:41:20;;;3613:28:19;;600:18:20;3613:28:19;487:187:20;1889:427:18;1982:29;:11;2003:7;1982:20;:29::i;:::-;1974:59;;;;-1:-1:-1;;;1974:59:18;;12163:2:20;1974:59:18;;;12145:21:20;12202:2;12182:18;;;12175:30;-1:-1:-1;;;12221:18:20;;;12214:47;12278:18;;1974:59:18;11961:341:20;1974:59:18;2059:1;2051:5;:9;2043:35;;;;-1:-1:-1;;;2043:35:18;;13217:2:20;2043:35:18;;;13199:21:20;13256:2;13236:18;;;13229:30;-1:-1:-1;;;13275:18:20;;;13268:43;13328:18;;2043:35:18;13015:337:20;2043:35:18;-1:-1:-1;;;;;2108:16:18;;2089;2108;;;:7;:16;;;;;;2134:24;:36;;2108:16;;;;2134:36;;2108:16;;2134:36;:::i;:::-;;;;-1:-1:-1;;;;;;;2181:16:18;;;;;;:7;:16;;;;;:24;;;2215;:33;;2200:5;;2181:16;2215:33;;2200:5;;2215:33;:::i;:::-;;;;-1:-1:-1;;2264:45:18;;;19163:25:20;;;19219:2;19204:18;;19197:34;;;-1:-1:-1;;;;;2264:45:18;;;;;19136:18:20;2264:45:18;;;;;;;1964:352;1889:427;;:::o;3718:479:0:-;3806:22;3814:4;3820:7;3806;:22::i;:::-;3801:390;;3989:28;4009:7;3989:19;:28::i;:::-;4088:38;4116:4;4123:2;4088:19;:38::i;:::-;3896:252;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;3896:252:0;;;;;;;;;;-1:-1:-1;;;3844:336:0;;;;;;;:::i;6926:561:19:-;7094:16;;;7108:1;7094:16;;;;;;;;7070:21;;7094:16;;;;;;;;;;-1:-1:-1;7094:16:19;7070:40;;7138:4;7120;7125:1;7120:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;7120:23:19;;;:7;;;;;;;;;;:23;;;;7163:10;;:17;;;-1:-1:-1;;;7163:17:19;;;;:10;;;;;:15;;:17;;;;;7120:7;;7163:17;;;;;:10;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7153:4;7158:1;7153:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;7153:27:19;;;:7;;;;;;;;;:27;7223:10;;7191:57;;7208:4;;7223:10;7236:11;7191:8;:57::i;:::-;7284:10;;:196;;-1:-1:-1;;;7284:196:19;;-1:-1:-1;;;;;7284:10:19;;;;:61;;:196;;7359:11;;7384:12;;7410:4;;7436;;7455:15;;7284:196;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7004:483;6926:561;;:::o;7520:498::-;7699:10;;7667:57;;7684:4;;-1:-1:-1;;;;;7699:10:19;7712:11;7667:8;:57::i;:::-;7764:10;;7958:14;;7764:247;;-1:-1:-1;;;7764:247:19;;7830:4;7764:247;;;21509:34:20;21559:18;;;21552:34;;;7764:10:19;21602:18:20;;;21595:34;;;21645:18;;;21638:34;-1:-1:-1;;;;;7958:14:19;;;21688:19:20;;;21681:44;7986:15:19;21741:19:20;;;21734:35;7764:10:19;;;:26;;7798:9;;21443:19:20;;7764:247:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;7520:498;;:::o;8615:156:10:-;8688:4;8711:53;8719:3;-1:-1:-1;;;;;8739:23:10;;8711:7;:53::i;8816:1935:19:-;8930:1;8921:6;:10;8913:36;;;;-1:-1:-1;;;8913:36:19;;22293:2:20;8913:36:19;;;22275:21:20;22332:2;22312:18;;;22305:30;-1:-1:-1;;;22351:18:20;;;22344:43;22404:18;;8913:36:19;22091:337:20;8913:36:19;9007:15;;8960:14;;;;-1:-1:-1;;;9007:15:19;;;;9006:16;:35;;;;-1:-1:-1;9026:15:19;;-1:-1:-1;;;9026:15:19;;;;9006:35;9057:15;;8988:53;;-1:-1:-1;;;;9057:15:19;;;;9052:720;;-1:-1:-1;;;;;3140:26:19;;;9088:17;3140:26;;;:17;:26;;;;;;;;;;;;;;;;;;;3737:21;;;:8;:21;;;;;;;;;;;;;;3140:26;;;;;;;;;3737:21;;;;;;9286:15;;;;;9297:4;9296:5;9286:15;:30;;;;;9306:10;9305:11;9286:30;:59;;;;-1:-1:-1;9334:10:19;;-1:-1:-1;;;;;9320:25:19;;;9334:10;;9320:25;;9286:59;9282:480;;;9401:16;:24;;;;;;;-1:-1:-1;9282:480:19;;;9450:4;:21;;;;;9459:12;9458:13;9450:21;:36;;;;;9476:10;9475:11;9450:36;9446:316;;;9543:16;:25;;;;;;;-1:-1:-1;9446:316:19;;;9594:6;9593:7;:16;;;;;9605:4;9604:5;9593:16;:47;;;;-1:-1:-1;9629:10:19;;-1:-1:-1;;;;;9613:27:19;;;9629:10;;9613:27;;9593:47;:64;;;;;9645:12;9644:13;9593:64;9589:173;;;9718:16;:29;;;;;;;-1:-1:-1;9589:173:19;9074:698;;;;9052:720;9810:10;:24;;;;;9833:1;9824:6;:10;9810:24;:43;;;;-1:-1:-1;;;;;;9839:14:19;;;;;;:8;:14;;;;;;;;9838:15;9810:43;9806:252;;;9869:28;9900:24;9918:4;9900:9;:24::i;:::-;9869:55;;9966:15;;9942:20;:39;9938:110;;10001:32;10014:15;;10031:1;10001:12;:32::i;:::-;9855:203;9806:252;10072:10;;10068:677;;10098:17;1351:5;10119:15;10128:6;10119;:15;:::i;:::-;10118:33;;;;:::i;:::-;10098:53;-1:-1:-1;10165:18:19;10186;10098:53;10186:6;:18;:::i;:::-;10252:16;:29;10165:39;;-1:-1:-1;10218:18:19;;1351:5;;10240:41;;-1:-1:-1;;;10252:29:19;;10239:59;10252:29;10240:9;:41;:::i;:::-;10239:59;;;;:::i;:::-;10218:80;-1:-1:-1;10317:14:19;;10313:141;;10351:23;10364:10;10351:23;;:::i;:::-;;;10392:47;10408:4;1204:42;10428:10;10392:15;:47::i;:::-;10472:13;;10468:99;;10505:47;10521:4;10535;10542:9;10505:15;:47::i;:::-;10585:14;;10581:90;;10619:37;10635:4;10641:2;10645:10;10619:15;:37::i;:::-;10084:597;;;10068:677;;;10701:33;10717:4;10723:2;10727:6;10701:15;:33::i;8297:150:10:-;8367:4;8390:50;8395:3;-1:-1:-1;;;;;8415:23:10;;8390:4;:50::i;2771:212:14:-;2932:44;2959:4;2965:2;2969:6;2932:26;:44::i;9098:115:10:-;9161:7;9187:19;9195:3;4537:18;;4455:107;9555:156;9629:7;9679:22;9683:3;9695:5;9679:3;:22::i;2102:149:6:-;2160:13;2192:52;-1:-1:-1;;;;;2204:22:6;;311:2;1513:437;1588:13;1613:19;1645:10;1649:6;1645:1;:10;:::i;:::-;:14;;1658:1;1645:14;:::i;:::-;1635:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1635:25:6;;1613:47;;-1:-1:-1;;;1670:6:6;1677:1;1670:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1670:15:6;;;;;;;;;-1:-1:-1;;;1695:6:6;1702:1;1695:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1695:15:6;;;;;;;;-1:-1:-1;1725:9:6;1737:10;1741:6;1737:1;:10;:::i;:::-;:14;;1750:1;1737:14;:::i;:::-;1725:26;;1720:128;1757:1;1753;:5;1720:128;;;-1:-1:-1;;;1800:5:6;1808:3;1800:11;1791:21;;;;;;;:::i;:::-;;;;1779:6;1786:1;1779:9;;;;;;;;:::i;:::-;;;;:33;-1:-1:-1;;;;;1779:33:6;;;;;;;;-1:-1:-1;1836:1:6;1826:11;;;;;1760:3;;;:::i;:::-;;;1720:128;;;-1:-1:-1;1865:10:6;;1857:55;;;;-1:-1:-1;;;1857:55:6;;22776:2:20;1857:55:6;;;22758:21:20;;;22795:18;;;22788:30;22854:34;22834:18;;;22827:62;22906:18;;1857:55:6;22574:356:20;2778:1388:10;2844:4;2981:19;;;:12;;;:19;;;;;;3015:15;;3011:1149;;3384:21;3408:14;3421:1;3408:10;:14;:::i;:::-;3456:18;;3384:38;;-1:-1:-1;3436:17:10;;3456:22;;3477:1;;3456:22;:::i;:::-;3436:42;;3510:13;3497:9;:26;3493:398;;3543:17;3563:3;:11;;3575:9;3563:22;;;;;;;;:::i;:::-;;;;;;;;;3543:42;;3714:9;3685:3;:11;;3697:13;3685:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;3797:23;;;:12;;;:23;;;;;:36;;;3493:398;3969:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4061:3;:12;;:19;4074:5;4061:19;;;;;;;;;;;4054:26;;;4102:4;4095:11;;;;;;;3011:1149;4144:5;4137:12;;;;;3011:1149;2850:1316;2778:1388;;;;:::o;7473:818:2:-;-1:-1:-1;;;;;7599:18:2;;7591:68;;;;-1:-1:-1;;;7591:68:2;;23269:2:20;7591:68:2;;;23251:21:20;23308:2;23288:18;;;23281:30;23347:34;23327:18;;;23320:62;-1:-1:-1;;;23398:18:20;;;23391:35;23443:19;;7591:68:2;23067:401:20;7591:68:2;-1:-1:-1;;;;;7677:16:2;;7669:64;;;;-1:-1:-1;;;7669:64:2;;23675:2:20;7669:64:2;;;23657:21:20;23714:2;23694:18;;;23687:30;23753:34;23733:18;;;23726:62;-1:-1:-1;;;23804:18:20;;;23797:33;23847:19;;7669:64:2;23473:399:20;7669:64:2;7744:38;7765:4;7771:2;7775:6;7744:20;:38::i;:::-;-1:-1:-1;;;;;7815:15:2;;7793:19;7815:15;;;;;;;;;;;7848:21;;;;7840:72;;;;-1:-1:-1;;;7840:72:2;;24079:2:20;7840:72:2;;;24061:21:20;24118:2;24098:18;;;24091:30;24157:34;24137:18;;;24130:62;-1:-1:-1;;;24208:18:20;;;24201:36;24254:19;;7840:72:2;23877:402:20;7840:72:2;-1:-1:-1;;;;;7946:15:2;;;:9;:15;;;;;;;;;;;7964:20;;;7946:38;;8161:13;;;;;;;;;;:23;;;;;;8210:26;;160:25:20;;;8161:13:2;;8210:26;;133:18:20;8210:26:2;;;;;;;8247:37;4709:225:14;2206:404:10;2269:4;4343:19;;;:12;;;:19;;;;;;2285:319;;-1:-1:-1;2327:23:10;;;;;;;;:11;:23;;;;;;;;;;;;;2507:18;;2485:19;;;:12;;;:19;;;;;;:40;;;;2539:11;;2285:319;-1:-1:-1;2588:5:10;2581:12;;1190:217:15;1328:4;1334:2;1338:6;457:17;;478:1;457:22;;:61;;;;;484:34;508:9;484:23;:34::i;:::-;483:35;457:61;453:173;;;575:17;;565:6;542:20;552:9;542;:20::i;:::-;:29;;;;:::i;:::-;:50;;534:81;;;;-1:-1:-1;;;534:81:15;;24486:2:20;534:81:15;;;24468:21:20;24525:2;24505:18;;;24498:30;-1:-1:-1;;;24544:18:20;;;24537:48;24602:18;;534:81:15;24284:342:20;534:81:15;1190:217;;;;;;:::o;4904:118:10:-;4971:7;4997:3;:11;;5009:5;4997:18;;;;;;;;:::i;:::-;;;;;;;;;4990:25;;4904:118;;;;:::o;196:286:20:-;254:6;307:2;295:9;286:7;282:23;278:32;275:52;;;323:1;320;313:12;275:52;349:23;;-1:-1:-1;;;;;;401:32:20;;391:43;;381:71;;448:1;445;438:12;679:250;764:1;774:113;788:6;785:1;782:13;774:113;;;864:11;;;858:18;845:11;;;838:39;810:2;803:10;774:113;;;-1:-1:-1;;921:1:20;903:16;;896:27;679:250::o;934:396::-;1083:2;1072:9;1065:21;1046:4;1115:6;1109:13;1158:6;1153:2;1142:9;1138:18;1131:34;1174:79;1246:6;1241:2;1230:9;1226:18;1221:2;1213:6;1209:15;1174:79;:::i;:::-;1314:2;1293:15;-1:-1:-1;;1289:29:20;1274:45;;;;1321:2;1270:54;;934:396;-1:-1:-1;;934:396:20:o;1335:131::-;-1:-1:-1;;;;;1410:31:20;;1400:42;;1390:70;;1456:1;1453;1446:12;1471:315;1539:6;1547;1600:2;1588:9;1579:7;1575:23;1571:32;1568:52;;;1616:1;1613;1606:12;1568:52;1655:9;1642:23;1674:31;1699:5;1674:31;:::i;:::-;1724:5;1776:2;1761:18;;;;1748:32;;-1:-1:-1;;;1471:315:20:o;1791:248::-;1859:6;1867;1920:2;1908:9;1899:7;1895:23;1891:32;1888:52;;;1936:1;1933;1926:12;1888:52;-1:-1:-1;;1959:23:20;;;2029:2;2014:18;;;2001:32;;-1:-1:-1;1791:248:20:o;2044:180::-;2103:6;2156:2;2144:9;2135:7;2131:23;2127:32;2124:52;;;2172:1;2169;2162:12;2124:52;-1:-1:-1;2195:23:20;;2044:180;-1:-1:-1;2044:180:20:o;2229:247::-;2288:6;2341:2;2329:9;2320:7;2316:23;2312:32;2309:52;;;2357:1;2354;2347:12;2309:52;2396:9;2383:23;2415:31;2440:5;2415:31;:::i;2481:456::-;2558:6;2566;2574;2627:2;2615:9;2606:7;2602:23;2598:32;2595:52;;;2643:1;2640;2633:12;2595:52;2682:9;2669:23;2701:31;2726:5;2701:31;:::i;:::-;2751:5;-1:-1:-1;2808:2:20;2793:18;;2780:32;2821:33;2780:32;2821:33;:::i;:::-;2481:456;;2873:7;;-1:-1:-1;;;2927:2:20;2912:18;;;;2899:32;;2481:456::o;3517:315::-;3585:6;3593;3646:2;3634:9;3625:7;3621:23;3617:32;3614:52;;;3662:1;3659;3652:12;3614:52;3698:9;3685:23;3675:33;;3758:2;3747:9;3743:18;3730:32;3771:31;3796:5;3771:31;:::i;:::-;3821:5;3811:15;;;3517:315;;;;;:::o;4026:160::-;4091:20;;4147:13;;4140:21;4130:32;;4120:60;;4176:1;4173;4166:12;4120:60;4026:160;;;:::o;4191:248::-;4256:6;4264;4317:2;4305:9;4296:7;4292:23;4288:32;4285:52;;;4333:1;4330;4323:12;4285:52;4369:9;4356:23;4346:33;;4398:35;4429:2;4418:9;4414:18;4398:35;:::i;:::-;4388:45;;4191:248;;;;;:::o;4444:203::-;4539:6;4592:3;4580:9;4571:7;4567:23;4563:33;4560:53;;;4609:1;4606;4599:12;4560:53;-1:-1:-1;4632:9:20;4444:203;-1:-1:-1;4444:203:20:o;4652:180::-;4708:6;4761:2;4749:9;4740:7;4736:23;4732:32;4729:52;;;4777:1;4774;4767:12;4729:52;4800:26;4816:9;4800:26;:::i;5526:315::-;5591:6;5599;5652:2;5640:9;5631:7;5627:23;5623:32;5620:52;;;5668:1;5665;5658:12;5620:52;5707:9;5694:23;5726:31;5751:5;5726:31;:::i;:::-;5776:5;-1:-1:-1;5800:35:20;5831:2;5816:18;;5800:35;:::i;6274:388::-;6342:6;6350;6403:2;6391:9;6382:7;6378:23;6374:32;6371:52;;;6419:1;6416;6409:12;6371:52;6458:9;6445:23;6477:31;6502:5;6477:31;:::i;:::-;6527:5;-1:-1:-1;6584:2:20;6569:18;;6556:32;6597:33;6556:32;6597:33;:::i;6667:380::-;6746:1;6742:12;;;;6789;;;6810:61;;6864:4;6856:6;6852:17;6842:27;;6810:61;6917:2;6909:6;6906:14;6886:18;6883:38;6880:161;;6963:10;6958:3;6954:20;6951:1;6944:31;6998:4;6995:1;6988:15;7026:4;7023:1;7016:15;7812:127;7873:10;7868:3;7864:20;7861:1;7854:31;7904:4;7901:1;7894:15;7928:4;7925:1;7918:15;7944:125;8009:9;;;8030:10;;;8027:36;;;8043:18;;:::i;8421:127::-;8482:10;8477:3;8473:20;8470:1;8463:31;8513:4;8510:1;8503:15;8537:4;8534:1;8527:15;8553:159;8620:20;;8680:6;8669:18;;8659:29;;8649:57;;8702:1;8699;8692:12;8717:981;8810:6;8863:3;8851:9;8842:7;8838:23;8834:33;8831:53;;;8880:1;8877;8870:12;8831:53;8913:2;8907:9;8955:3;8947:6;8943:16;9025:6;9013:10;9010:22;8989:18;8977:10;8974:34;8971:62;8968:185;;;9075:10;9070:3;9066:20;9063:1;9056:31;9110:4;9107:1;9100:15;9138:4;9135:1;9128:15;8968:185;9169:2;9162:22;9208:26;9224:9;9208:26;:::i;:::-;9200:6;9193:42;9268:37;9301:2;9290:9;9286:18;9268:37;:::i;:::-;9263:2;9255:6;9251:15;9244:62;9339:37;9372:2;9361:9;9357:18;9339:37;:::i;:::-;9334:2;9326:6;9322:15;9315:62;9410:37;9443:2;9432:9;9428:18;9410:37;:::i;:::-;9405:2;9397:6;9393:15;9386:62;9482:38;9515:3;9504:9;9500:19;9482:38;:::i;:::-;9476:3;9468:6;9464:16;9457:64;9555:38;9588:3;9577:9;9573:19;9555:38;:::i;:::-;9549:3;9541:6;9537:16;9530:64;9628:38;9661:3;9650:9;9646:19;9628:38;:::i;:::-;9622:3;9610:16;;9603:64;9614:6;8717:981;-1:-1:-1;;;8717:981:20:o;9703:335::-;9905:2;9887:21;;;9944:2;9924:18;;;9917:30;-1:-1:-1;;;9978:2:20;9963:18;;9956:41;10029:2;10014:18;;9703:335::o;11257:171::-;11325:6;11364:10;;;11352;;;11348:27;;11387:12;;;11384:38;;;11402:18;;:::i;11433:168::-;11506:9;;;11537;;11554:15;;;11548:22;;11534:37;11524:71;;11575:18;;:::i;11606:217::-;11646:1;11672;11662:132;;11716:10;11711:3;11707:20;11704:1;11697:31;11751:4;11748:1;11741:15;11779:4;11776:1;11769:15;11662:132;-1:-1:-1;11808:9:20;;11606:217::o;11828:128::-;11895:9;;;11916:11;;;11913:37;;;11930:18;;:::i;13700:251::-;13770:6;13823:2;13811:9;13802:7;13798:23;13794:32;13791:52;;;13839:1;13836;13829:12;13791:52;13871:9;13865:16;13890:31;13915:5;13890:31;:::i;15764:135::-;15803:3;15824:17;;;15821:43;;15844:18;;:::i;:::-;-1:-1:-1;15891:1:20;15880:13;;15764:135::o;16942:168::-;17009:6;17035:10;;;17047;;;17031:27;;17070:11;;;17067:37;;;17084:18;;:::i;19242:812::-;19653:25;19648:3;19641:38;19623:3;19708:6;19702:13;19724:75;19792:6;19787:2;19782:3;19778:12;19771:4;19763:6;19759:17;19724:75;:::i;:::-;-1:-1:-1;;;19858:2:20;19818:16;;;19850:11;;;19843:40;19908:13;;19930:76;19908:13;19992:2;19984:11;;19977:4;19965:17;;19930:76;:::i;:::-;20026:17;20045:2;20022:26;;19242:812;-1:-1:-1;;;;19242:812:20:o;20059:127::-;20120:10;20115:3;20111:20;20108:1;20101:31;20151:4;20148:1;20141:15;20175:4;20172:1;20165:15;20191:972;20445:4;20493:3;20482:9;20478:19;20524:6;20513:9;20506:25;20550:2;20588:6;20583:2;20572:9;20568:18;20561:34;20631:3;20626:2;20615:9;20611:18;20604:31;20655:6;20690;20684:13;20721:6;20713;20706:22;20759:3;20748:9;20744:19;20737:26;;20798:2;20790:6;20786:15;20772:29;;20819:1;20829:195;20843:6;20840:1;20837:13;20829:195;;;20908:13;;-1:-1:-1;;;;;20904:39:20;20892:52;;20999:15;;;;20964:12;;;;20940:1;20858:9;20829:195;;;-1:-1:-1;;;;;;;21080:32:20;;;;21075:2;21060:18;;21053:60;-1:-1:-1;;;21144:3:20;21129:19;21122:35;21041:3;20191:972;-1:-1:-1;;;20191:972:20:o;21780:306::-;21868:6;21876;21884;21937:2;21925:9;21916:7;21912:23;21908:32;21905:52;;;21953:1;21950;21943:12;21905:52;21982:9;21976:16;21966:26;;22032:2;22021:9;22017:18;22011:25;22001:35;;22076:2;22065:9;22061:18;22055:25;22045:35;;21780:306;;;;;:::o;22433:136::-;22472:3;22500:5;22490:39;;22509:18;;:::i;:::-;-1:-1:-1;;;22545:18:20;;22433:136::o;22935:127::-;22996:10;22991:3;22987:20;22984:1;22977:31;23027:4;23024:1;23017:15;23051:4;23048:1;23041:15

Swarm Source

ipfs://f4f556e7fa0da4ef89bb1c88f77c2cdf6e41fd7c1380b97cd9f5c0a094948e38
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.