ETH Price: $3,594.77 (+8.89%)

Token

ChungaLungaCoin ($CL)
 

Overview

Max Total Supply

10,000,000,000 $CL

Holders

122

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
40,849,999.363500001050596365 $CL

Value
$0.00
0x968bfbf98b68beb0f8cb07432d237a264b740c21
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:
ChungaLungaCoin

Compiler Version
v0.8.3+commit.8d00100c

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-08-11
*/

// SPDX-License-Identifier: MIT

// File: @uniswap/v2-core/contracts/interfaces/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: @uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol

pragma solidity >=0.5.0;


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

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

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

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

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

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

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

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

    function initialize(address, address) external;
}

// File: @uniswap/v2-periphery/contracts/interfaces/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: @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol

pragma solidity >=0.6.2;



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: contracts/interfaces/ISafetyControl.sol

pragma solidity ^0.8.3;


/**
 * Enables safety and general transaction restrictions control.
 * 
 * Safety control :
 *  1. enabling/disabling anti pajeet system (APS). Can be called by admins to decide whether additional limitiations to sales should be imposed on not
 *  2. enabling/disabling trade control  system (TCS).
 *  3. enabling/disabling sending of tokens between accounts
 *  
 * General control:
 *  1. presale period. During presale all taxes are disabled
 *  2. trade. Before trade is open, no transactions are allowed
 *  3. LP state control. Before LP has been created, trade cannot be opened.
 * 
 */
interface ISafetyControl {

    /**
    * Defines state of APS after change of some of properties.
    * Properties:
    *   - enabled -> is APS enabled
    *   - txLimit -> max number of tokens (in percentage of total supply supporting 1 decimal point) one can buy/sell. E.g. 1 means 0.1%, 10 means 1% etc. 
    *   - thresh -> number of tokens(in wei). If one holds more that this number than he cannot sell more than 20% of his tokens at once
    *   - interval -> number of minutes between two consecutive sales
    */
    event APSStateChanged(
        bool enabled,
        uint256 txLimit,
        uint256 thresh,
        uint256 interval
    );
    
    /**
     * Enables/disables Anti pajeet system.
     * If enabled it will impose sale restrictions:
     *   - cannot sell more than 0.2% of total supply at once
	 *   - if owns more than 1% total supply:
	 *	    - can sell at most 20% at once (but not more than 0.2 of total supply)
	 *	    - can sell once every hour
     * 
     * emits APSStateChanged
	 * 
	 * @param enabled   Defines state of APS. true or false
     */
    function setAPS(bool enabled) external;

    /**
     * Enables/disables Trade Control System.
     * If enabled it will impose sale restrictions:
     *   - max TX will be checked
	 *   - holders will not be able to purchase and hold more than _holderLimit tokens
	 *	 - single account can sell once every 2 mins
	 * 
	 * @param enabled   Defines state of TCS. true or false
     */
    function setTCS(bool enabled) external;

    /**
     * Defines new Anti pajeet system threshold in percentage. Value supports single digit, Meaning 10 means 1%.
     * Examples:
     *    to set 1%: 10
     *    to set 0.1%: 1
     * 
     * emits APSStateChanged
     *
	 * @param thresh  New threshold in percentage of total supply. Value supports single digit.
     */
    function setAPSThreshPercent(uint256 thresh) external;

    /**
    * Defines new Anti pajeet system threshold in tokens. Minimal amount is 1000 tokens
    * 
    * emits APSStateChanged
	* @param thresh  New threshold in token amount
    */
    function setAPSThreshAmount(uint256 thresh) external;

    /**
    * Defines new Anti pajeet system TX limit. Value supports single digit, Meaning 10 means 1%.
    * Examples:
    *    to set 1%: 10
    *    to set 0.1%: 1
    * 
    * emits APSStateChanged
    *
	* @param txLimit  New TX limit in percentage of total supply. Value supports single digit
    */
    function setAPSTxLimit(uint256 txLimit) external;

    /**
    * Sets new interval user will have to wait in between two consecutive sales, if APS is enabled.
    * Default value is 1 hour
    * 
    * 
    * emits APSStateChanged
    *
    * @param interval   interval between two consecutive sales, in minutes. E.g. 60 means 1 hour
    */
    function setAPSInterval(uint256 interval) external;
    
    /**
     * Upon start of presale all taxes are disabled
	 * Once presale is stopped, taxes are enabled once more
	 * 
	 * @param start     Defines state of Presale. started or stopped
     */
    function setPreSale(bool start) external;
    
    /**
     * Only once trading is open will transactions be allowed. 
     * Trading is disabled by default.
     * Liquidity MUST be provided before trading can be opened
     */
    function openTrading() external;
    
    /**
     * Adds initial liquidity to LP from contract's supply of coins and tokens.
     */
	function addInitialLiquidity() external;

    /**
    * Enables/disables sharing of tokens between accounts.
    * If enabled, sending tokens from one account to another is permitted. 
    * If disabled, sending tokens from one account to another will be blocked.
    *
    * @param enabled    True if sending between account is permitter, otherwise false      
    */
    function setAccountShare(bool enabled) external;

}
// File: contracts/interfaces/IFeeControl.sol

pragma solidity ^0.8.3;


/**
 * Defines control over:
 *  - who will be paying fees
 *  - when will fees be applied
 */
interface IFeeControl {
    event ExcludeFromFees (
        address indexed account,
        bool isExcluded
    );
    
    event TakeFeeOnlyOnSwap (
        bool enabled
    );
	
	event MinTokensBeforeSwapUpdated (
        uint256 minTokensBeforeSwap
    );
    
    /**
     * Exclude or include account in fee system. Excluded accounts don't pay any fee.
     *
     * @param account   Account address
     * @param exclude   If true account will be excluded, otherwise it will be included in fee
     */
    function feeControl(address account, bool exclude) external;

    /**
     * Is account excluded from paying fees?
     *
     * @param account   Account address
     */
    function isExcludedFromFee(address account) external view returns(bool);
    /**
     * Taking fee only on swaps.
     * Emits TakeFeeOnlyOnSwap(true) event.
     * 
     * @param onSwap    Take fee only on swap (true) or always (false)
     */
     function takeFeeOnlyOnSwap(bool onSwap) external;
     
    /**
	* Changes number of tokens collected before swap can be triggered
    * - emits MinTokensBeforeSwapUpdated event
    *
    * @param thresh     New number of tokens that must be collected before swap is triggered
	*/
	function changeSwapThresh(uint256 thresh) external;
}
// File: contracts/interfaces/IFee.sol

pragma solidity ^0.8.3;


/**
 * Defines Fees:
 *  - marketing
 *  - liquidity
 * All fees are using 1 decimal: 1000 means 100%, 100 means 10%, 10 means 1%, 1 means 0.1%
 */
interface IFee {
    /**
     * Struct of fees.
     */
    struct Fees {
      uint256 marketingFee;
      uint256 liquidityFee;
    }
    
    /**
     * Marketing wallet can be changed
     *
     * @param newWallet     Address of new marketing wallet
     */
    function changeMarketingWallet(address newWallet) external;

    /**
	* Changing fees. Distinguishes between buy and sell fees
    *
    * @param liquidityFee   New liquidity fee in percentage written as integer divisible by 1000. E.g. 5% => 0.05 => 50/1000 => 50
    * @param marketingFee   New marketing fee in percentage written as integer divisible by 1000. E.g. 5% => 0.05 => 50/1000 => 50
    * @param isBuy          Are fees for buy or not(for sale)
	*/
    function setFees(uint256 liquidityFee, uint256 marketingFee, bool isBuy)  external;
    
    /**
     * Control whether tokens collected from fees will be automatically swapped or not
     *
     * @param enable        True if swap should be enabled, otherwise false
     */
    function setSwapOfFeeTokens(bool enable) external;
}
// File: contracts/interfaces/IBlacklisting.sol

pragma solidity ^0.8.3;


/**
 * Some blacklisting/whitelisting functionalities:
 *  - adding account to list of blacklisted/whitelisted accounts
 *  - removing account from list of blacklisted/whitelisted accounts
 *  - check whether account is blacklisted/whitelisted accounts (against internal list)
 */
interface IBlacklisting {

    /**
     * Define account status in blacklist
	 *
	 * @param account   Account to be added or removed to/from blacklist
	 * @param add       Should account be added or removed from blacklist
     */
    function setBlacklist(address account, bool add) external;

    /**
     * Define account status in whitelist
	 *
	 * @param account   Account to be added or removed to/from whitelist
	 * @param add       Should account be added or removed from whitelist
     */
    function setWhitelist(address account, bool add) external;
    /**
     * Checks whether account is blacklisted
     */
    function isBlacklisted(address account) external view returns(bool);
	/**
     * Checks whether account is whitelisted
     */
    function isWhitelisted(address account) external view returns(bool);

    /**
    *  Define fee charged to blacklist. Fee supports singe decimal place, i.e it should be multiplied by 10 to get unsigned int: 100 means 10%, 10 means 1% and 1 means 0.1%
    */
    function setBlacklistFee(uint256 blacklistFee) external;
    
}
// File: @openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

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

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

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

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// 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: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @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: contracts/interfaces/IChungaLungaCoin.sol

pragma solidity ^0.8.3;







interface IChungaLungaCoin is IERC20, IERC20Metadata, IBlacklisting, ISafetyControl, IFee, IFeeControl {
    
    event UpdateSwapV2Router (
        address indexed newAddress
    );
    
    event SwapAndLiquifyEnabledUpdated (
        bool enabled
    );

    event MarketingSwap (
        uint256 tokensSwapped,
        uint256 ethReceived,
        bool success
    );
    
    event SwapAndLiquify (
        uint256 tokensSwapped,
        uint256 ethReceived,
        uint256 tokensIntoLiqudity
    );

    /**
    * Defines new state of properties TCS uses after some property was changed
    * Properties:
    *   - enabled ->is TCS system enabled
    *   - maxTxLimit -> max number of tokens (in wei) one can sell/buy at once
    *   - holderLimit -> max number of tokens one account can hold
    *   - interval ->interval between two consecutive sales in minutes
    */
    event TCSStateChanged(
        bool enabled,
        uint256 maxTxLimit,
        uint256 holderLimit,
        uint256 interval
    );


    /**
    * (un)Setting *swapV2Pair address.
    *
    * @param pair       address of AMM pair
    * @param value      true if it's to be treated as AMM pair, otherwise false
    */
    function setAMMPair(address pair, bool value) external;
    
    /**
     * Max TX can be set either by providing percentage of total supply or exact amount.
     *
     * !MAX TX percentage MUST be between 1 and 10!
     * 
     * emits TCSStateChanged
     *
     * @param maxTxPercent    new percentage used to calculate max number of tokens that can be transferred at the same time
     */
    function setMaxTxPercent(uint256 maxTxPercent) external;
    /**
     * max TX can be set either by providing percentage of total supply or exact amount.
     *
     * emits TCSStateChanged
     *
     * @param maxTxAmount    new max number of tokens that can be transferred at the same time
     */
    function setMaxTxAmount(uint256 maxTxAmount) external;

    /**
     * Excluded accounts are not limited by max TX amount.
	 * Included accounts are limited by max TX amount.
     *
     * @param account   account address
     * @param exclude   true if account is to be excluded from max TX control. Otherwise false
     */
    function maxTxControl(address account, bool exclude) external;
    /**
     * Is account excluded from MAX TX limitations?
     *
     * @param account   account address
     * @return          true if account is excluded, otherwise false
     */
    function isExcludedFromMaxTx(address account) external view returns(bool);

    /**
    * Defines new limit to max token amount holder can possess.
    *
    * ! Holder limit MUST be greater than 0.5% total supply
    *
    * emits TCSStateChanged
    *
    * @param limit      Max number of tokens one holder can possess
    */
    function setHolderLimit(uint256 limit) external;
    
    /**
     * Once set, LP provisioning from liquidity fees will start. 
     * Disabled by default. 
     * Must be called manually
     * - emits SwapAndLiquifyEnabledUpdated event
     *
     * @param enabled   true if swap is enabled, otherwise false
     */
    function setSwapAndLiquifyEnabled(bool enabled) external;
    
    /**
     * It will exclude sale helper router address and presale router address from fee's and rewards
     *
     * @param helperRouter  address of router used by helper 
     * @param presaleRouter address of presale router(contract) used by helper 
     */
    function setHelperSaleAddress(address helperRouter, address presaleRouter) external;
    
    /**
     * Any leftover coin balance on contract can be transferred (withdrawn) to chosen account.
     * Used to clear contract state.
     *
     * @param recipient     address of recipient
     */
    function withdrawLocked(address payable recipient) external;

    /**
     * Function to withdraw collected fees to marketing wallet in case automatic swap is disabled.
     * 
     * ! Will fail it swap is not disabled
     */
    function withdrawFees() external;
    
    /**
     * Updates address of V2 swap router
     * - emits UpdateSwapV2Router event
     *
     * @param newAddress    address of swap router
     */
    function updateSwapV2Router(address newAddress) external;

    /**
     * Starts whitelisted process. 
     * Whitelisted process will is valid for limited time only starting from current time. 
     * It will last for at most provided duration in minutes.
     *
     * @param duration      Duration in minutes. 
     */
    function startWhitelistProcess(uint256 duration) external;    
}
// File: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/Address.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;




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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [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) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

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

        /// @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 on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

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

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

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

        return result;
    }
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// 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: @openzeppelin/contracts/utils/introspection/ERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;


/**
 * @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: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

// File: @openzeppelin/contracts/access/IAccessControl.sol


// 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: @openzeppelin/contracts/access/IAccessControlEnumerable.sol


// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)

pragma solidity ^0.8.0;


/**
 * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
 */
interface IAccessControlEnumerable is IAccessControl {
    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) external view returns (address);

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}

// File: @openzeppelin/contracts/utils/Context.sol


// 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: @openzeppelin/contracts/token/ERC20/ERC20.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;




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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `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;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/access/AccessControl.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)

pragma solidity ^0.8.0;





/**
 * @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(uint160(account), 20),
                        " 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());
        }
    }
}

// File: @openzeppelin/contracts/access/AccessControlEnumerable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)

pragma solidity ^0.8.0;




/**
 * @dev Extension of {AccessControl} that allows enumerating the members of each role.
 */
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
    using EnumerableSet for EnumerableSet.AddressSet;

    mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;

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

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {
        return _roleMembers[role].at(index);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {
        return _roleMembers[role].length();
    }

    /**
     * @dev Overload {_grantRole} to track enumerable memberships
     */
    function _grantRole(bytes32 role, address account) internal virtual override {
        super._grantRole(role, account);
        _roleMembers[role].add(account);
    }

    /**
     * @dev Overload {_revokeRole} to track enumerable memberships
     */
    function _revokeRole(bytes32 role, address account) internal virtual override {
        super._revokeRole(role, account);
        _roleMembers[role].remove(account);
    }
}

// File: contracts/ChungaLungaCoin.sol


pragma solidity ^0.8.3;


//import '@openzeppelin/contracts/utils/introspection/ERC165.sol';



//import '@openzeppelin/contracts/security/ReentrancyGuard.sol';











/**
*
* https://www.chungalungacoin.com/
* https://t.me/chungalunga
* https://twitter.com/chungalungacoin
*
*/
contract ChungaLungaCoin is IChungaLungaCoin, ERC20, Ownable, AccessControlEnumerable {
    using SafeMath for uint256;
    using Address for address;
    using SafeERC20 for IERC20;

    event StateProgress (
        bool liquidityAdded,
        bool whitelistStarted,
        bool tradeOpened
    );

    event WhitelistProcessStarted (
        uint256 duration
    );
    
    struct TaxedValues{
      uint256 amount;
      uint256 tAmount;
      uint256 tMarketing;
      uint256 tLiquidity;
    }
	
	struct SwapValues{
		uint256 tMarketing;
		uint256 tLiquidity;
		uint256 tHalfLiquidity;
		uint256 tTotal;
		uint256 swappedBalance;
	}
	
	// 
	// CONSTANTS
	//
	uint256 private constant MAX = ~uint256(0);

	/* Using 18 decimals */
	uint8 private constant DECIMALS = 18;
	
	/* Total supply : 10_000_000_000 tokens (10 Billion) */
	uint256 private constant TOKENS_INITIAL = 10 * 10 ** 9;
	
	/* Minimal number of tokens that must be collected before swap can be triggered: 1000. Real threshold cannot be set below this value */
	uint256 private constant MIN_SWAP_THRESHOLD = 1 * 10 ** 3 * 10 ** uint256(DECIMALS);

    /* By what to divide calculated fee to compensate for supported decimals */
    uint256 private constant DECIMALS_FEES = 1000;
	
	/* Max amount of individual fee. 6.0% */
	uint256 private constant LIMIT_FEES = 60;
	
	/* Max amount of total fees. 10.0% */
	uint256 private constant LIMIT_TOTAL_FEES = 100;

    /* Number of minutes between 2 sales */
    uint256 private constant TCS_TIME_INTERVAL = 2;
	
	/* Dead address */
	address private constant deadAddress = 0x000000000000000000000000000000000000dEaD;
	
	bytes32 public constant CL_ADMIN_ROLE = keccak256("CL_ADMIN_ROLE");
    bytes32 public constant CL_CTRL_ROLE = keccak256("CL_CTRL_ROLE");
	
	// 
	// MEMBERS
	//
	
	/* How much can each address allow for another address */
    mapping (address => mapping (address => uint256)) private _allowances;
	
	/* Map of addresses and whether they are excluded from fee */
    mapping (address => bool) private _isExcludedFromFee;
    
    /* Map of addresses and whether they are excluded from max TX check */
    mapping (address => bool) private _isExcludedFromMaxTx;
    
    /* Map of blacklisted addresses */
    mapping(address => bool) private _blacklist;
	
	/* Map of whitelisted addresses */
    mapping(address => bool) private _whitelist;
	
	/* Fee that will be charged to blacklisted accounts. Default is 90% */
	uint256 private _blacklistFee = 900;
    
    /* Marketing wallet address */
    address public marketingWalletAddress;

    /* Number of tokens currently pending swap for marketing */
    uint256 public tPendingMarketing;
    /* Number of tokens currently pending swap for liquidity */
    uint256 public tPendingLiquidity;
	
	/* Total tokens in wei. Will be created during initial mint in constructor */
    uint256 private _tokensTotal = TOKENS_INITIAL * 10 ** uint256(DECIMALS);
	
	/* Total fees taken so far */
    Fees private _totalTakenFees = Fees(
    {marketingFee: 0,
      liquidityFee: 0
    });
    
    Fees private _buyFees = Fees(
    {marketingFee: 30,
      liquidityFee: 20
    });
    
    Fees private _previousBuyFees = Fees(
     {marketingFee: _buyFees.marketingFee,
      liquidityFee: _buyFees.liquidityFee
    });
    
    Fees private _sellFees = Fees(
     {marketingFee: 30,
      liquidityFee: 20
    });
    
    Fees private _previousSellFees = Fees(
     {marketingFee: _sellFees.marketingFee,
      liquidityFee: _sellFees.liquidityFee
    });
    
	/* Swap and liquify safety flag */
    bool private _inSwapAndLiquify;
	
	/* Whether swap and liquify is enabled or not. Enabled by default */
    bool private _swapAndLiquifyEnabled = true;
    
	/* Anti Pajeet system. Disabled by default */
    bool public apsEnabled = false;

    /* Trade control system. Disabled by default */
    bool public tcsEnabled = false;

    /* Is whitelisted process active */
    bool private _whProcActive = false;

    /* When did whitelisted process start? */
    uint256 private _whStart = 0;

    /* Duration of whitelisted process */
    uint256 private _whDuration = 1;

    /* Account sharing system (sending of tokens between accounts. Disabled by default */
    bool private _accSharing = false;

    /* Anti Pajeet system threshold. Defaults to 25M tokens. If a single account holds more that that number of tokens APS limits will be applied */
    uint256 private _apsThresh = 25 * 10 ** 6 * 10 ** uint256(DECIMALS);

    /* Anti Pajeet system single transaction limit. Defaults to 0.4% (40M tokens). Can be dynamically adjusted */
    uint256 private _apsLimit = 4;

    /* Anti Pajeet system interval between two consecutive sales. In minutes. It defines when is the earlies user can sell depending on his last sale. Can be as low as 1 min. Defaults to 1440 mins (24 hours).  */
    uint256 private _apsInterval = 1440;
	
	/* Was LP provided? False by default */
	bool public liquidityAdded = false;
	
	/* Is trade open? False by default */
	bool public tradingOpen = false;
	
	/* Should tokens in marketing wallet be swapped automatically */
	bool private _swapMarketingTokens = true;
	
	/* Should fees be applied only on swaps? Otherwise, all transactions will be taxed */
	bool public feeOnlyOnSwap = false;
	
	/* Mapping of previous sales by address. Used to limit sell occurrence */
    mapping (address => uint256) private _previousSale;

    /* Mapping of previous buys by address. Used to limit buy occurrence */
    mapping (address => uint256) private _previousBuy;
    
	/* Maximal transaction amount -> cannot be higher than available token supply. Initially 20M of tokens can be sold/bought. It will be dynamically adjusted */
    uint256 private _maxTxAmount = 20 * 10 ** 6 * 10 ** uint256(DECIMALS);

    /* Maximal amount single holder can possess -> cannot be higher than available token supply. Initially it will be set to 2% of total supply. It will be dynamically adjusted */
    uint256 private _maxHolderAmount = (_tokensTotal * 2) / 100;
	
	/* Min number of tokens to trigger sell and add to liquidity. Initially, 300k tokens */
    uint256 private _swapThresh =  300 * 10 ** 3 * 10 ** uint256(DECIMALS);
    
    /* *Swap V2 router */
    IUniswapV2Router02 private _swapV2Router;
    
    /* Swap V2 pair */
    address private _swapV2Pair;
	
	/* Map of AMMs. Special rules apply when AMM is "to" */
	mapping (address => bool) public ammPairs;
    
    constructor () ERC20("ChungaLungaCoin", "$CL") {
		
        _changeMarketingWallet(address(0x0E7E45f0BE3c46907E6aF055AE1157E2Bb19aAf2));
		
		_setupRole(CL_CTRL_ROLE, msg.sender);
	
        // 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D is RouterV2 at mainnet
        _setupSwap(address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D));
        _setupExclusions();
		
		_setRoleAdmin(CL_ADMIN_ROLE, CL_ADMIN_ROLE);
        _setRoleAdmin(CL_CTRL_ROLE, CL_ADMIN_ROLE);

        _setupRole(CL_ADMIN_ROLE, msg.sender);
        _setupRole(CL_ADMIN_ROLE, address(this));

        _setupRole(CL_CTRL_ROLE, msg.sender);
        _setupRole(CL_CTRL_ROLE, address(this));
		
        _mint(msg.sender, _tokensTotal);
		
		transferOwnership(msg.sender);
    }
    
    //
    // EXTERNAL ACCESS
    //

	function addCTRLMember(address account) public virtual onlyRole(CL_ADMIN_ROLE) {
        grantRole(CL_CTRL_ROLE, account);
    }

    /**
    * Fetches how many tokens were taken as fee so far
    *
    * @return (marketingFeeTokens, liquidityFeeTokens)
    */
    function totalTakenFees() public view returns (uint256, uint256) {
        return (_totalTakenFees.marketingFee, _totalTakenFees.liquidityFee);
    }

    /**
    * Fetches current fee settings: buy or sell.
    *
    * @param isBuy  true if buy fees are requested, otherwise false
    * @return (marketingFee, liquidityFee)
    */
    function currentFees(bool isBuy) public view returns (uint256, uint256) {
        if(isBuy){
            return (_buyFees.marketingFee, _buyFees.liquidityFee);
        } else {
            return (_sellFees.marketingFee, _sellFees.liquidityFee);
        }
    }
    
    function feeControl(address account, bool exclude) override external onlyRole(CL_CTRL_ROLE) {
        _isExcludedFromFee[account] = exclude;
    }
    
    /* Check whether account is exclude from fee */
    function isExcludedFromFee(address account) override external view returns(bool) {
        return _isExcludedFromFee[account];
    }
    
    function maxTxControl(address account, bool exclude) external override onlyRole(CL_CTRL_ROLE) {
        _isExcludedFromMaxTx[account] = exclude;
    }
    
    function isExcludedFromMaxTx(address account) public view override returns(bool) {
        return _isExcludedFromMaxTx[account];
    }

    function setHolderLimit(uint256 limit) external override onlyRole(CL_CTRL_ROLE) {
        require(limit > 0 && limit < TOKENS_INITIAL, "HOLDER_LIMIT1");

        uint256 new_limit = limit * 10 ** uint256(DECIMALS);

        // new limit cannot be less than 0.5%
        require(new_limit > ((_tokensTotal * 5) / DECIMALS_FEES), "HOLDER_LIMIT2");

        _maxHolderAmount = new_limit;

        emit TCSStateChanged(tcsEnabled, _maxTxAmount, _maxHolderAmount, TCS_TIME_INTERVAL);
    }

    /* It will exclude sale helper router address and presale router address from fee's and rewards */
    function setHelperSaleAddress(address helperRouter, address presaleRouter) external override onlyRole(CL_CTRL_ROLE) {
        _excludeAccount(helperRouter, true);
        _excludeAccount(presaleRouter, true);
    }

    /* Enable Trade control system. Imposes limitations on buy/sell */
    function setTCS(bool enabled) override external onlyRole(CL_CTRL_ROLE) {
        tcsEnabled = enabled;

        emit TCSStateChanged(tcsEnabled, _maxTxAmount, _maxHolderAmount, TCS_TIME_INTERVAL);
    }

    /**
     * Returns TCS state:
     * - max TX amount in wei
     * - max holder amount in wei
     * - TCS buy/sell interval in minutes
     */
    function getTCSState() public view onlyRole(CL_CTRL_ROLE) returns(uint256, uint256, uint256) {
        return (_maxTxAmount, _maxHolderAmount, TCS_TIME_INTERVAL);
    }
    
	/* Enable anti-pajeet system. Imposes limitations on sale */
    function setAPS(bool enabled) override external onlyRole(CL_CTRL_ROLE) {
        apsEnabled = enabled;

        emit APSStateChanged(apsEnabled, _apsLimit, _apsThresh, _apsInterval);
    }

	/* Sets new APS threshold. It cannot be set to more than 5% */
    function setAPSThreshPercent(uint256 thresh) override external onlyRole(CL_CTRL_ROLE) {
        require(thresh < 50, "APS-THRESH-PERCENT");

        _apsThresh = _tokensTotal.mul(thresh).div(DECIMALS_FEES);

        emit APSStateChanged(apsEnabled, _apsLimit, _apsThresh, _apsInterval);
    }

    function setAPSThreshAmount(uint256 thresh) override external onlyRole(CL_CTRL_ROLE) {
        require(thresh > 1000 && thresh < TOKENS_INITIAL, "APS-THRESH-AMOUNT");

        _apsThresh = thresh * 10 ** uint256(DECIMALS);

        emit APSStateChanged(apsEnabled, _apsLimit, _apsThresh, _apsInterval);
    }

    /* Sets new APS tx limit. It cannot be set to more than 2% */
    function setAPSTxLimit(uint256 txLimit) override external onlyRole(CL_CTRL_ROLE) {
        require(txLimit < 20, "APS-TX-LIMIT");

        _apsLimit = txLimit;

        emit APSStateChanged(apsEnabled, _apsLimit, _apsThresh, _apsInterval);
    }

    /* Sets new min APS sale interval. In minutes */
    function setAPSInterval(uint256 interval) override external onlyRole(CL_CTRL_ROLE) {
        require(interval > 0, "APS-INTERVAL-0");

        _apsInterval = interval;

        emit APSStateChanged(apsEnabled, _apsLimit, _apsThresh, _apsInterval);
    }

    /**
     * Returns APS state:
     * - TX limit in percentage
     * - threshold in tokens
     * - interval in minutes
     */
    function getAPSState() public view onlyRole(CL_CTRL_ROLE) returns(uint256, uint256, uint256) {
        return (_apsLimit, _apsThresh, _apsInterval);
    }

    /* wnables/disables account sharing: sending of tokens between accounts */
    function setAccountShare(bool enabled) override external onlyRole(CL_CTRL_ROLE) {
        _accSharing = enabled;
    }
    
	/* Changing marketing wallet */
    function changeMarketingWallet(address account) override external onlyRole(CL_CTRL_ROLE) {
        _changeMarketingWallet(account);
    }
    
    function setFees(uint256 liquidityFee, uint256 marketingFee, bool isBuy) external override onlyRole(CL_CTRL_ROLE) {
        // fees are setup so they can not exceed 30% in total
        // and specific limits for each one.
        require(marketingFee + liquidityFee <= LIMIT_TOTAL_FEES, "FEE-MAX");
       
        _setMarketingFeePercent(marketingFee, isBuy);
        _setLiquidityFeePercent(liquidityFee, isBuy);
    }
   
    /* Define MAX TX amount. In percentage of total supply */
    function setMaxTxPercent(uint256 maxTxPercent) override external onlyRole(CL_CTRL_ROLE) {
        require(maxTxPercent > 0 && maxTxPercent < 100, "MAXTX_PERC_LIMIT");
        _maxTxAmount = _tokensTotal.mul(maxTxPercent).div(DECIMALS_FEES);

        emit TCSStateChanged(tcsEnabled, _maxTxAmount, _maxHolderAmount, TCS_TIME_INTERVAL);
    }
    
	/* Define MAX TX amount. In token count */
    function setMaxTxAmount(uint256 maxTxAmount) override external onlyRole(CL_CTRL_ROLE) {
        require(maxTxAmount >= 1 && maxTxAmount < TOKENS_INITIAL, "MAXTX_AMNT_LIMIT");
        _maxTxAmount = maxTxAmount * 10 ** uint256(DECIMALS);

        emit TCSStateChanged(tcsEnabled, _maxTxAmount, _maxHolderAmount, TCS_TIME_INTERVAL);
    }

    /* Enable LP provisioning */
    function setSwapAndLiquifyEnabled(bool enabled) override external onlyRole(CL_CTRL_ROLE) {
        _swapAndLiquifyEnabled = enabled;
        emit SwapAndLiquifyEnabledUpdated(enabled);
    }
	
	/* Define new swap threshold. Cannot be less than MIN_SWAP_THRESHOLD: 1000 tokens */
	function changeSwapThresh(uint256 thresh) override external onlyRole(CL_CTRL_ROLE){
        uint256 newThresh = thresh * 10 ** uint256(DECIMALS);

		require(newThresh > MIN_SWAP_THRESHOLD, "THRESH-LOW");

		_swapThresh = newThresh;
	}

    /* take a look at current swap threshold */
    function swapThresh() public view onlyRole(CL_CTRL_ROLE) returns(uint256) {
        return _swapThresh;
    }
    
	/* Once presale is done and LP is created, trading can be enabled for all. Only once this is set will normal transactions be completed successfully */
    function openTrading() override external onlyRole(CL_CTRL_ROLE) {
        require(liquidityAdded, "LIQ-NONE");
       _openTrading();
    }

    function _openTrading() internal {
        tradingOpen = true;

        emit StateProgress(true, true, true);
    }

    function startWhitelistProcess(uint256 duration) override external onlyRole(CL_CTRL_ROLE) {
        require(duration > 1, "WHT-DUR-LOW");
        _whProcActive = true;
        _whDuration = duration;
        _whStart = block.timestamp;

        // set MAX TX limit to 20M tokens
        _maxTxAmount = 20 * 10 ** 6 * 10 ** uint256(DECIMALS);

        // make sure trading is closed
        tradingOpen = false;

        // emit current state
        emit StateProgress(true, true, false);

        // emit start of whitelist process
        emit WhitelistProcessStarted(duration);
    }

	/* Sets should tokens collected through fees be automatically swapped to ETH or not */
    function setSwapOfFeeTokens(bool enabled) override external onlyRole(CL_CTRL_ROLE) {
        _swapMarketingTokens = enabled;
    }
    
	/* Sets should fees be taken only on swap or on all transactions */
    function takeFeeOnlyOnSwap(bool onSwap) override external onlyRole(CL_CTRL_ROLE) {
        feeOnlyOnSwap = onSwap;
        emit TakeFeeOnlyOnSwap(feeOnlyOnSwap);
    }
	
	/* Should be called once LP is created. Manually or programatically (by calling #addInitialLiquidity()) */
	function defineLiquidityAdded() public onlyRole(CL_CTRL_ROLE) {
        liquidityAdded = true;

        emit StateProgress(true, false, false);
    }
	
	function addInitialLiquidity() override external onlyRole(CL_CTRL_ROLE) {
	    // approve router to "route" tx in our name
        _approve(address(this), address(_swapV2Router), _tokensTotal);
        
        // add all ETH from this address together with all the tokens to LP (should be initial LP provision! In case that's already done manually, use #defineLiquidityAdded function)
        _swapV2Router.addLiquidityETH{value: address(this).balance}
            (address(this),balanceOf(address(this)),0,0,owner(),block.timestamp);
            
        defineLiquidityAdded();
        
        IERC20(_swapV2Pair).approve(address(_swapV2Router),type(uint256).max);
    }
    
	/* withdraw any ETH balance stuck in contract */
    function withdrawLocked(address payable recipient) external override onlyRole(CL_CTRL_ROLE) {
        require(recipient != address(0), 'ADDR-0');
        require(address(this).balance > 0, 'BAL-0');
	
        uint256 amount = address(this).balance;
        // address(this).balance = 0;
    
        (bool success,) = payable(recipient).call{value: amount}('');
    
        if(!success) {
          revert();
        }
    }

    function withdrawFees() external override onlyRole(CL_CTRL_ROLE) {
        require(!_swapAndLiquifyEnabled, "WITHDRAW-SWAP");

        super._transfer(address(this), marketingWalletAddress, balanceOf(address(this)));

        tPendingMarketing = 0;
        tPendingLiquidity = 0;
    }
    
    function isBlacklisted(address account) external view override returns(bool) {
        return _blacklist[account];
    }
	
	function isWhitelisted(address account) external view override returns(bool) {
        return _whitelist[account];
    }
    
    function setBlacklist(address account, bool add) external override onlyRole(CL_CTRL_ROLE) {
		require(!add || !_whitelist[account], 'BLST-1');
		_blacklist[account] = add;
    }
    
    function setWhitelist(address account, bool add) external override onlyRole(CL_CTRL_ROLE) {
		require(!add || !_blacklist[account], 'BLST-2');
        _whitelist[account] = add;
    }
	
	function setBlacklistFee(uint256 blacklistFee) external override onlyRole(CL_CTRL_ROLE) {
		_blacklistFee = blacklistFee;
	}

    function bulkWhitelist(address[] calldata addrs) external onlyRole(CL_CTRL_ROLE) {
        for (uint i=0; i<addrs.length; i++){
            _whitelist[addrs[i]] = true;
        }
    }
	
	/* To be called whan presale begins/ends. It will remove/add fees */
	function setPreSale(bool start) external override onlyRole(CL_CTRL_ROLE) {
		if(start) { // presale started
			// remove all fees (buy)
			_removeAllFee(true);
			// remove all fees (sell)
			_removeAllFee(false);
		} else { // presale stopped
			// restore all fees (buy)
			_restoreAllFee(true);
			// restore all fees (sell)
			_restoreAllFee(false);
		}
    }
    
    function updateSwapV2Router(address newAddress) external override onlyRole(CL_CTRL_ROLE) {
        require(newAddress != address(0), "R2-1");
        _setupSwap(newAddress);
    }
    
     //to receive ETH from *swapV2Router when swaping. msg.data must be empty
    receive() external payable {}

    // Fallback function is called when msg.data is not empty
    //fallback() external payable {}
    
    //
    // PRIVATE ACCESS
    //
    
    function _setupSwap(address routerAddress) private {
        // Uniswap V2 router: 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
        
        _swapV2Router = IUniswapV2Router02(routerAddress);
    
        // create a swap pair for this new token
        _swapV2Pair = IUniswapV2Factory(_swapV2Router.factory()).createPair(address(this), _swapV2Router.WETH());

		_setAMMPair(address(_swapV2Pair), true);

        //_approve(owner(), address(_swapV2Router), type(uint256).max);

        _isExcludedFromMaxTx[address(_swapV2Router)] = true;

        _approve(owner(), address(_swapV2Router), type(uint256).max);
        ERC20(address(_swapV2Router.WETH())).approve(address(_swapV2Router), type(uint256).max);
        ERC20(address(_swapV2Router.WETH())).approve(address(this), type(uint256).max);
		
		emit UpdateSwapV2Router(routerAddress);
    }
	
	function setAMMPair(address pair, bool value) external override onlyRole(CL_CTRL_ROLE) {
        _setAMMPair(pair, value);
    }

    function _setAMMPair(address pair, bool value) private {
        ammPairs[pair] = value;

        _isExcludedFromMaxTx[pair] = value;
    }
    
    function _excludeAccount(address addr, bool ex) private {
         _isExcludedFromFee[addr] = ex;
         _isExcludedFromMaxTx[addr] = ex;
    }
    
    function _setupExclusions() private {
        _excludeAccount(msg.sender, true);
        _excludeAccount(address(this), true);
        _excludeAccount(owner(), true);
		_excludeAccount(deadAddress, true);
        _excludeAccount(marketingWalletAddress, true);
    }
    
    function _changeMarketingWallet(address addr) internal {
        require(addr != address(0), "ADDR-0");
        _excludeAccount(marketingWalletAddress, false);
		
        marketingWalletAddress = addr;
		
		_excludeAccount(addr, true);
    }
    
    function _isBuy(address from) internal view returns(bool) {
        //return from == address(_swapV2Pair) || ammPairs[from];
        return ammPairs[from];
    }
    
    function _isSell(address to) internal view returns(bool) {
        //return to == address(_swapV2Pair) || ammPairs[to];
        return ammPairs[to];
    }
    
    function _checkTxLimit(address from, address to, uint256 amount) internal view {
        if (_isBuy(from)) { // buy
			require(amount <= _maxTxAmount || _isExcludedFromMaxTx[to], "TX-LIMIT-BUY");
        } else  if (_isSell(to)) { // sell
            require(amount <= _maxTxAmount || _isExcludedFromMaxTx[from], "TX-LIMIT-SELL");
        } else { // transfer
			require(amount <= _maxTxAmount || (_isExcludedFromMaxTx[from] && _isExcludedFromMaxTx[to]), "TX-LIMIT");
        }
    }
    
    function _setMarketingFeePercent(uint256 fee, bool isBuy) internal {
        require(fee <= LIMIT_FEES, "FEE-LIMIT-M");
        
        if(isBuy){
            _previousBuyFees.marketingFee = _buyFees.marketingFee;
            _buyFees.marketingFee = fee;
        } else {
            _previousSellFees.marketingFee = _sellFees.marketingFee;
            _sellFees.marketingFee = fee;
        }
    }
    
    function _setLiquidityFeePercent(uint256 liquidityFee, bool isBuy) internal {
        require(liquidityFee <= LIMIT_FEES, "FEE-LIMIT-L");
        
         if(isBuy){
            _previousBuyFees.liquidityFee = _buyFees.liquidityFee;
            _buyFees.liquidityFee = liquidityFee;
        } else {
            _previousSellFees.liquidityFee = _sellFees.liquidityFee;
            _sellFees.liquidityFee = liquidityFee;
        }
    }

    function _getValues(uint256 amount, bool isBuy) private view returns (TaxedValues memory totalValues) {
        totalValues.amount = amount;
        totalValues.tMarketing = _calculateMarketingFee(amount, isBuy);
        totalValues.tLiquidity = _calculateLiquidityFee(amount, isBuy);
        
        totalValues.tAmount = amount.sub(totalValues.tMarketing).sub(totalValues.tLiquidity);
        
        return totalValues;
    }
    
    function _calculateMarketingFee(uint256 amount, bool isBuy) private view returns (uint256) {
        if(isBuy){
            return _buyFees.marketingFee > 0 ?
                amount.mul(_buyFees.marketingFee).div(DECIMALS_FEES) : 0;
        } else {
            return _sellFees.marketingFee > 0 ?
                amount.mul(_sellFees.marketingFee).div(DECIMALS_FEES) : 0;
        }
    }

    function _calculateLiquidityFee(uint256 amount, bool isBuy) private view returns (uint256) {
        if(isBuy){
            return _buyFees.liquidityFee > 0 ?
                amount.mul(_buyFees.liquidityFee).div(DECIMALS_FEES) : 0;
        } else {
            return _sellFees.liquidityFee > 0 ?
                amount.mul(_sellFees.liquidityFee).div(DECIMALS_FEES) : 0; 
        }
    }
    
    function _removeAllFee(bool isBuy) private {
        if(isBuy){
            _previousBuyFees = _buyFees;
            _buyFees.liquidityFee = 0;
            _buyFees.marketingFee = 0;
        } else {
            _previousSellFees = _sellFees;
            _sellFees.liquidityFee = 0;
            _sellFees.marketingFee = 0;
        }
    }
    
    function _restoreAllFee(bool isBuy) private {
        if(isBuy){
            _buyFees = _previousBuyFees;
        } else {
            _sellFees = _previousSellFees;
        }
    }
    
    /**
    * Transfer codes:
    *   - FROM-ADDR-0 -> from address is 0
    *   - TO-ADDR-0 -> to address is 0
    *   - ADDR-0 -> if some address is 0 
    *   - CNT-0 -> if some amount is 0
    */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        require(from != address(0), "FROM-ADDR-0");
        require(to != address(0), "TO-ADDR-0");
        if (amount == 0) {
            super._transfer(from, to, 0);
            return;
        }

        if(_blacklist[from] || _blacklist[to]) {
			_blacklistDefense(from, to, amount);
            return;
        }

        if (!_inSwapAndLiquify) {

            // whitelist process check
            _whitelistProcessCheck();

            // TCS  (Trade Control System) check
            _tcsCheck(from, to, amount);
            
            // APS (Anti Pajeet System) check
            _apsCheck(from, to, amount);

            // DLP (Delayed Provision)
            _delayedProvision(from, to);
        }

        //indicates if fee should be deducted from transfer
        bool takeFee = !_inSwapAndLiquify;

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

        /*
        // take fee only on swaps depending on input flag
        if (feeOnlyOnSwap && !_isBuy(from) && !_isSell(to)) {
            takeFee = false;
        }
        */
        
        //transfer amount, it will take tax, special, liquidity fee
        _tokenTransfer(from, to, amount, takeFee);
    }
	
	function _blacklistDefense(address from, address to, uint256 amount) private {
		uint256 tFee = amount * _blacklistFee / DECIMALS_FEES;
		uint256 tRest = amount - tFee;

        super._transfer(from, address(this), tFee);
        super._transfer(from, to, tRest);

        uint256 totalFeeP = 0;
        uint256 mFee = 0;
        uint256 lFee = 0;
        if (_isBuy(from)) {
            totalFeeP = _buyFees.liquidityFee + _buyFees.marketingFee;
            if (totalFeeP > 0) {
                lFee = _buyFees.liquidityFee > 0 ? tFee * _buyFees.liquidityFee / totalFeeP : 0;
                mFee = tFee - lFee;
            }
        } else {
            totalFeeP = _sellFees.liquidityFee + _sellFees.marketingFee;
            if (totalFeeP > 0) {
                lFee = _sellFees.liquidityFee > 0 ? tFee * _sellFees.liquidityFee / totalFeeP : 0;
                mFee = tFee - lFee;
            }
        }

        if (totalFeeP > 0) {
            tPendingMarketing += mFee;
            tPendingLiquidity += lFee;
            _totalTakenFees.marketingFee += mFee;
            _totalTakenFees.liquidityFee += lFee;
        }
		
	}

    function _whitelistProcessCheck() private {
        if (_whProcActive) {
            if (_whStart + (_whDuration * 1 minutes) < block.timestamp) {
                // whitelist process has expired. Disable it
                _whProcActive = false;

            	// set MAX TX limit to 30M tokens
                _maxTxAmount = 30 * 10 ** 6 * 10 ** uint256(DECIMALS);

                // open trading
                _openTrading();
            }
        }
    }
    
    /**
    * TCS codes:
    *   - TCS-TRADE -> trade is not open
    *   - TCS-ACC-SHARE -> account sharing is disabled
    *   - TCS-HOLDER-LIMIT -> holder limit is exceeded
    *   - TCS-TIME -> must wait for at least 2min before another sell
    *   - TX-LIMIT-BUY -> transaction limit has been reached during buy
    *   - TX-LIMIT-SELL -> transaction limit has been reached during sell
    *   - TX-LIMIT -> transaction limit has been reached during share
    *
    */
    function _tcsCheck(address from, address to, uint256 amount) view private {
        //
        // TCS (Trade Control System):
		// 1. trade MUST be opened
		// 2. liquidity MUST be provided (trade can be open ONLY IF liquidity is provided)
        // 3. trade imposes MAX token amount per TX restrictions
        // 4. inter account sharing of tokens is checked depending on whether it's enabled/disabled
        // 5. trade imposes MAX tokens that single holder can possess
        // 6. if APS is disabled sale can be done once every 2 mins
		//

        if (tcsEnabled) {

            // check TX limit
            _checkTxLimit(from, to, amount);

            if (!_whProcActive || (!_whitelist[from] && !_whitelist[to])) {
                require(tradingOpen, "TCS-TRADE");
                require(_accSharing || _isBuy(from) || _isSell(to), "TCS-ACC-SHARE"); // either acc sharing is enabled, or at least one of from-to is AMM
            }

            // check max holder amount limit
            if (_isBuy(from)) {
                require(amount + balanceOf(to) <= _maxHolderAmount, "TCS-HOLDER-LIMIT");
            } else if(!_isSell(to)) {
                require(amount + balanceOf(to) <= _maxHolderAmount, "TCS-HOLDER-LIMIT");
            }

            // buy/sell limit
            if (_isSell(to)) {
                require( (_previousSale[from] + (TCS_TIME_INTERVAL * 1 minutes)) < block.timestamp, "TCS-TIME");
            } else if (_isBuy(from)) {
                require( (_previousBuy[to] + (TCS_TIME_INTERVAL * 1 minutes)) < block.timestamp, "TCS-TIME");
            } else {
                // token sharing 
                require( (_previousSale[from] + (TCS_TIME_INTERVAL * 1 minutes)) < block.timestamp, "TCS-TIME");
                require( (_previousBuy[to] + (TCS_TIME_INTERVAL * 1 minutes)) < block.timestamp, "TCS-TIME");
            }
        }
    }
    
    /**
    * APS codes:
    *   - APS-SUPPLY -> cannot buy/sell more than 1% of total supply at once
    *   - APS-BALANCE -> cannot sell more than 20% of current balance if holds more than apsThresh tokens
    *   - APS-TIME -> must wait until _apsInterval passes before another sell
    */
    function _apsCheck(address from, address to, uint256 amount) view private {
        //
		// APS (Anti Pajeet System):
		// 1. cannot sell more than _apsLimit % of total supply at once
		// 2. can sell at most 20% of tokens in possession at once if holder has more than _apsThresh tokens
		// 3. can sell once every _apsInterval (60) minutes
		//
		
        if (apsEnabled) {

            require(amount < (totalSupply() * _apsLimit / DECIMALS_FEES), "APS-SUPPLY");
            
            // Sell in progress
            if(_isSell(to)) {

                uint256 fromBalance = balanceOf(from);	// how many tokens does account own

                // if total number of tokens is above threshold, only 20% of tokens can be sold at once!
                if(fromBalance >= _apsThresh) {
                    require(amount < (fromBalance / (5)), "APS-BALANCE");
                }

                // at most 1 sell every _apsInterval minutes (60 by default)
                require( (_previousSale[from] + (_apsInterval * 1 minutes)) < block.timestamp, "APS-TIME");
            }
			
        }
    }
	
	function _swapAndLiquifyAllFees() private {
        uint256 contractBalance = balanceOf(address(this));

        uint256 tTotal = tPendingLiquidity + tPendingMarketing;
        
        if(contractBalance == 0 || tTotal == 0 || tTotal < _swapThresh) {return;}
        
		uint256 tLiqHalf = contractBalance * tPendingLiquidity / tTotal / 2;
        uint256 amountToSwapForETH = contractBalance.sub(tLiqHalf);
        
        // starting contract's ETH balance
        uint256 initialBalance = address(this).balance;

		// swap tokens for ETH
        _swapTokensForEth(amountToSwapForETH, address(this));
		
		// how much ETH did we just swap into?
        uint256 swappedBalance = address(this).balance.sub(initialBalance);
		
		// calculate ETH shares
		uint256 cMarketing = swappedBalance.mul(tPendingMarketing).div(tTotal);
        uint256 cLiq = swappedBalance - cMarketing;

		// liquify
		if(tPendingLiquidity > 0 && cLiq > 0){
		
			//
			// DLP (Delayed Liquidity Provision):
			// - adding to liquidity only after some threshold has been met to avoid LP provision on every transaction
			//  * NOTE: liquidity provision MUST be enabled first
			//  * NOTE: don't enrich liquidity if sender is swap pair
			//
		
			// add liquidity to LP
			_addLiquidity(tLiqHalf, cLiq);
        
			emit SwapAndLiquify(tLiqHalf, cLiq, tPendingLiquidity.sub(tLiqHalf));
		}
        
		// transfer to marketing
        (bool sent,) = address(marketingWalletAddress).call{value: cMarketing}("");
        emit MarketingSwap(tPendingMarketing, cMarketing, sent);

         // reset token count
        tPendingLiquidity = 0;
        tPendingMarketing = 0;
    }
    
    function _delayedProvision(address from, address to) private {

        if (
            !_inSwapAndLiquify &&
            !_isBuy(from) &&
            _swapAndLiquifyEnabled &&
            !_isExcludedFromFee[from] &&
            !_isExcludedFromFee[to]
        ) {
            _inSwapAndLiquify = true;
			_swapAndLiquifyAllFees();
            _inSwapAndLiquify = false;
		}
    }

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

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

        // make the swap
        _swapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of ETH
            path,
            account,
            block.timestamp
        );
    }

    function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
        // approve token transfer to cover all possible scenarios
        _approve(address(this), address(_swapV2Router), tokenAmount);

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

    //this method is responsible for taking all fee, if takeFee is true
    function _tokenTransfer(address sender, address recipient, uint256 amount, bool takeFee) private {
        bool isBuy = _isBuy(sender);

        uint256 fees = 0;
        if (takeFee) {
            TaxedValues memory totalValues = _getValues(amount, isBuy);

            fees = totalValues.tMarketing + totalValues.tLiquidity;

            if(fees > 0) {

                tPendingMarketing += totalValues.tMarketing;
                tPendingLiquidity += totalValues.tLiquidity;

                _totalTakenFees.marketingFee += totalValues.tMarketing;
                _totalTakenFees.liquidityFee += totalValues.tLiquidity;

                super._transfer(sender, address(this), fees);

                amount -= fees;
            }
        }

        if (isBuy) {
            _previousBuy[recipient] = block.timestamp;
        } else if(_isSell(recipient)) {
            _previousSale[sender] = block.timestamp;
        } else {
            // token sharing
            _previousBuy[recipient] = block.timestamp;
            _previousSale[sender] = block.timestamp;
        }

        super._transfer(sender, recipient, amount);

    }
    
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"},{"indexed":false,"internalType":"uint256","name":"txLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"thresh","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interval","type":"uint256"}],"name":"APSStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"ExcludeFromFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokensSwapped","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethReceived","type":"uint256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"MarketingSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minTokensBeforeSwap","type":"uint256"}],"name":"MinTokensBeforeSwapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"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":false,"internalType":"bool","name":"liquidityAdded","type":"bool"},{"indexed":false,"internalType":"bool","name":"whitelistStarted","type":"bool"},{"indexed":false,"internalType":"bool","name":"tradeOpened","type":"bool"}],"name":"StateProgress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokensSwapped","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethReceived","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensIntoLiqudity","type":"uint256"}],"name":"SwapAndLiquify","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"SwapAndLiquifyEnabledUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"},{"indexed":false,"internalType":"uint256","name":"maxTxLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"holderLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interval","type":"uint256"}],"name":"TCSStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"TakeFeeOnlyOnSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"UpdateSwapV2Router","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"WhitelistProcessStarted","type":"event"},{"inputs":[],"name":"CL_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CL_CTRL_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addCTRLMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addInitialLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ammPairs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"apsEnabled","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":"address[]","name":"addrs","type":"address[]"}],"name":"bulkWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"changeMarketingWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"thresh","type":"uint256"}],"name":"changeSwapThresh","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isBuy","type":"bool"}],"name":"currentFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defineLiquidityAdded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"exclude","type":"bool"}],"name":"feeControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeOnlyOnSwap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAPSState","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"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":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTCSState","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"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":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromMaxTx","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityAdded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingWalletAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"exclude","type":"bool"}],"name":"maxTxControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","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":"address","name":"pair","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setAMMPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setAPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"interval","type":"uint256"}],"name":"setAPSInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"thresh","type":"uint256"}],"name":"setAPSThreshAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"thresh","type":"uint256"}],"name":"setAPSThreshPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"txLimit","type":"uint256"}],"name":"setAPSTxLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setAccountShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"add","type":"bool"}],"name":"setBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"blacklistFee","type":"uint256"}],"name":"setBlacklistFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidityFee","type":"uint256"},{"internalType":"uint256","name":"marketingFee","type":"uint256"},{"internalType":"bool","name":"isBuy","type":"bool"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"helperRouter","type":"address"},{"internalType":"address","name":"presaleRouter","type":"address"}],"name":"setHelperSaleAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setHolderLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxTxAmount","type":"uint256"}],"name":"setMaxTxAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxTxPercent","type":"uint256"}],"name":"setMaxTxPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"start","type":"bool"}],"name":"setPreSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setSwapAndLiquifyEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setSwapOfFeeTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setTCS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"add","type":"bool"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"startWhitelistProcess","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":"swapThresh","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tPendingLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tPendingMarketing","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"onSwap","type":"bool"}],"name":"takeFeeOnlyOnSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tcsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTakenFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"updateSwapV2Router","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"}],"name":"withdrawLocked","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052610384600d55620000186012600a62001000565b62000029906402540be400620010e8565b601155604080518082018252600080825260209182018190526012818155601382905583518085018552601e808252601491850182905280825560158290558551808701875281815285018290526016819055601782905585518087018752818152850182905260188190556019829055855180870190965280865294909301839052601a849055601b92909255601c805464ffffffff001916610100179055601d556001909155601f805460ff19169055620000e890600a62001000565b620000f89063017d7840620010e8565b60205560046021556105a06022556023805463ffffffff191662010000179055620001266012600a62001000565b62000136906301312d00620010e8565b602655606460115460026200014c9190620010e8565b62000158919062000f92565b602755620001696012600a62001000565b6200017890620493e0620010e8565b6028553480156200018857600080fd5b506040518060400160405280600f81526020016e21b43ab733b0a63ab733b0a1b7b4b760891b815250604051806040016040528060038152602001620910d360ea1b8152508160039080519060200190620001e592919062000e7f565b508051620001fb90600490602084019062000e7f565b50505062000218620002126200035160201b60201c565b62000355565b62000237730e7e45f0be3c46907e6af055ae1157e2bb19aaf2620003a7565b6200025260008051602062005d138339815191523362000462565b62000271737a250d5630b4cf539739df2c5dacb4c659f2488d62000472565b6200027b620008fe565b6200029660008051602062005cf383398151915280620009f4565b620002c060008051602062005d1383398151915260008051602062005cf3833981519152620009f4565b620002db60008051602062005cf38339815191523362000462565b620002f660008051602062005cf38339815191523062000462565b6200031160008051602062005d138339815191523362000462565b6200032c60008051602062005d138339815191523062000462565b620003403360115462000a3f60201b60201c565b6200034b3362000b26565b6200115d565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038116620003ec5760405162461bcd60e51b81526020600482015260066024820152650414444522d360d41b60448201526064015b60405180910390fd5b600e80546001600160a01b039081166000908152600960208181526040808420805460ff19908116909155600a80845282862080548316905587546001600160a01b0319169689169687179097559484529181528183208054851660019081179091559490529020805490911690911790555b50565b6200046e828262000ba2565b5050565b602980546001600160a01b0319166001600160a01b0383169081179091556040805163c45a015560e01b8152905163c45a015591600480820192602092909190829003018186803b158015620004c757600080fd5b505afa158015620004dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000502919062000f25565b6001600160a01b031663c9c6539630602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b1580156200056057600080fd5b505afa15801562000575573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200059b919062000f25565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381600087803b158015620005e457600080fd5b505af1158015620005f9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200061f919062000f25565b602a80546001600160a01b0319166001600160a01b039283169081179091556000908152602b60209081526040808320805460ff199081166001908117909255600a909352818420805484168217905560295485168452922080549091169091179055600554620006a091166029546001600160a01b031660001962000be5565b602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b158015620006ef57600080fd5b505afa15801562000704573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200072a919062000f25565b60295460405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b390604401602060405180830381600087803b1580156200077957600080fd5b505af11580156200078e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007b4919062000f55565b50602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b1580156200080457600080fd5b505afa15801562000819573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200083f919062000f25565b60405163095ea7b360e01b815230600482015260001960248201526001600160a01b03919091169063095ea7b390604401602060405180830381600087803b1580156200088b57600080fd5b505af1158015620008a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008c6919062000f55565b506040516001600160a01b038216907f7e336871192a11cf6144610c966672324a2721225248a567fd1211203248469e90600090a250565b3360009081526009602081815260408084208054600160ff199182168117909255600a8085528387208054831684179055308752858552838720805483168417905580855283872080548316841790556005546001600160a01b039081168852868652848820805484168517905581865284882080548416851790557f960b1051749987b45b5679007fff577a1c2f763ec21c15a6c5eb19307500378580548416851790557f20677881080440a9b3c87e826370bb5d9c2f74efd4dede686d52d77a6a09f8bb8054841685179055600e54168752948452828620805482168317905593909252909220805490911690911790555b565b600082815260066020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6001600160a01b03821662000a975760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401620003e3565b806002600082825462000aab919062000f77565b90915550506001600160a01b0382166000908152602081905260408120805483929062000ada90849062000f77565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36200046e565b62000b3062000d0d565b6001600160a01b03811662000b975760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620003e3565b6200045f8162000355565b62000bb9828262000d6960201b620023a21760201c565b600082815260076020908152604090912062000be09183906200242862000e0d821b17901c565b505050565b6001600160a01b03831662000c495760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401620003e3565b6001600160a01b03821662000cac5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401620003e3565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6005546001600160a01b03163314620009f25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620003e3565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff166200046e5760008281526006602090815260408083206001600160a01b03851684529091529020805460ff1916600117905562000dc93390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600062000e24836001600160a01b03841662000e2d565b90505b92915050565b600081815260018301602052604081205462000e765750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e27565b50600062000e27565b82805462000e8d906200110a565b90600052602060002090601f01602090048101928262000eb1576000855562000efc565b82601f1062000ecc57805160ff191683800117855562000efc565b8280016001018555821562000efc579182015b8281111562000efc57825182559160200191906001019062000edf565b5062000f0a92915062000f0e565b5090565b5b8082111562000f0a576000815560010162000f0f565b60006020828403121562000f37578081fd5b81516001600160a01b038116811462000f4e578182fd5b9392505050565b60006020828403121562000f67578081fd5b8151801515811462000f4e578182fd5b6000821982111562000f8d5762000f8d62001147565b500190565b60008262000fae57634e487b7160e01b81526012600452602481fd5b500490565b80825b600180861162000fc7575062000ff7565b81870482111562000fdc5762000fdc62001147565b8086161562000fea57918102915b9490941c93800262000fb6565b94509492505050565b600062000e2460001984846000826200101c5750600162000f4e565b816200102b5750600062000f4e565b81600181146200104457600281146200104f5762001083565b600191505062000f4e565b60ff84111562001063576200106362001147565b6001841b9150848211156200107c576200107c62001147565b5062000f4e565b5060208310610133831016604e8410600b8410161715620010bb575081810a83811115620010b557620010b562001147565b62000f4e565b620010ca848484600162000fb3565b808604821115620010df57620010df62001147565b02949350505050565b600081600019048311821515161562001105576200110562001147565b500290565b600181811c908216806200111f57607f821691505b602082108114156200114157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b614b86806200116d6000396000f3fe60806040526004361061044b5760003560e01c80638cab3a6611610234578063cc6c914f1161012e578063e720c7eb116100b6578063f2fde38b1161007a578063f2fde38b14610d80578063f73b554114610da0578063fe575a8714610dc0578063ffb54a9914610df9578063ffbd7b3a14610e1857610452565b8063e720c7eb14610cdd578063eae9bdb714610cfd578063ec28438a14610d1d578063ee294a1b14610d3d578063ee88ac8e14610d5e57610452565b8063d547741f116100fd578063d547741f14610c43578063d944392314610c63578063dd62ed3e14610c7d578063de74407114610c9d578063e1a4206714610cbd57610452565b8063cc6c914f14610bc3578063cd2cd9e414610be3578063d158272d14610c03578063d543dbeb14610c2357610452565b8063a72905a2116101bc578063bbeb5db011610180578063bbeb5db014610b39578063c49b9a8014610b4e578063c8125a7814610b6e578063c9567bf914610b8e578063ca15c87314610ba357610452565b8063a72905a214610a89578063a9059cbb14610ab9578063b743d07214610ad9578063bb095b9b14610af9578063bb85c6d114610b1957610452565b806395d89b411161020357806395d89b4114610a14578063a15af6f714610a29578063a217fddf14610a3e578063a457c2d714610a53578063a5f2aba514610a7357610452565b80638cab3a66146109825780638da5cb5b146109a25780639010d07c146109d457806391d14854146109f457610452565b8063313ce567116103455780635738047a116102cd578063715018a611610291578063715018a6146108e4578063753643c5146108f9578063761ce8411461092d5780637ac0d1551461094d57806388ffe7db1461096d57610452565b80635738047a1461082b578063658c27a91461084b578063665e3728146108845780636f44902f146108a457806370a08231146108c457610452565b80633b25f85c116103145780633b25f85c1461077c578063476343ee1461079c5780634ccf15ef146107b15780635342acb4146107d257806353d6fd591461080b57610452565b8063313ce567146106e757806336568abe1461070357806339509351146107235780633af32abf1461074357610452565b8063153b0d1e116103d35780631bd96bd6116103975780631bd96bd61461062e57806323b872dd14610657578063248a9ca3146106775780632d99d32e146106a75780632f2ff15d146106c757610452565b8063153b0d1e14610595578063165f16d0146105b557806318160ddd146105d957806319d659b5146105ee5780631b7852181461060e57610452565b806306fdde031161041a57806306fdde03146104e357806309552a3114610505578063095ea7b3146105355780630a7c0163146105555780630d95ccc91461057557610452565b806301ffc9a7146104575780630210a83d1461048c57806304046287146104a357806306f91d59146104c357610452565b3661045257005b600080fd5b34801561046357600080fd5b506104776104723660046146ba565b610e38565b60405190151581526020015b60405180910390f35b34801561049857600080fd5b506104a1610e63565b005b3480156104af57600080fd5b506104a16104be366004614625565b610fd5565b3480156104cf57600080fd5b506104a16104de36600461465d565b611067565b3480156104ef57600080fd5b506104f86111ac565b60405161048391906147f7565b34801561051157600080fd5b5061051a61123e565b60408051938452602084019290925290820152606001610483565b34801561054157600080fd5b5061047761055036600461458a565b61126e565b34801561056157600080fd5b506104a161057036600461465d565b611286565b34801561058157600080fd5b506104a1610590366004614625565b6112a4565b3480156105a157600080fd5b506104a16105b036600461455d565b6112ef565b3480156105c157600080fd5b506105cb60105481565b604051908152602001610483565b3480156105e557600080fd5b506002546105cb565b3480156105fa57600080fd5b506104a16106093660046144ad565b61138e565b34801561061a57600080fd5b506104a1610629366004614625565b6113ee565b34801561063a57600080fd5b506012546013545b60408051928352602083019190915201610483565b34801561066357600080fd5b5061047761067236600461451d565b611423565b34801561068357600080fd5b506105cb61069236600461465d565b60009081526006602052604090206001015490565b3480156106b357600080fd5b506104a16106c236600461455d565b611449565b3480156106d357600080fd5b506104a16106e2366004614675565b611470565b3480156106f357600080fd5b5060405160128152602001610483565b34801561070f57600080fd5b506104a161071e366004614675565b611495565b34801561072f57600080fd5b5061047761073e36600461458a565b61150f565b34801561074f57600080fd5b5061047761075e3660046144ad565b6001600160a01b03166000908152600c602052604090205460ff1690565b34801561078857600080fd5b506104a161079736600461455d565b611531565b3480156107a857600080fd5b506104a1611575565b3480156107bd57600080fd5b50601c54610477906301000000900460ff1681565b3480156107de57600080fd5b506104776107ed3660046144ad565b6001600160a01b031660009081526009602052604090205460ff1690565b34801561081757600080fd5b506104a161082636600461455d565b611602565b34801561083757600080fd5b50601c546104779062010000900460ff1681565b34801561085757600080fd5b506104776108663660046144ad565b6001600160a01b03166000908152600a602052604090205460ff1690565b34801561089057600080fd5b506104a161089f366004614625565b6116a1565b3480156108b057600080fd5b506106426108bf366004614625565b61170e565b3480156108d057600080fd5b506105cb6108df3660046144ad565b611732565b3480156108f057600080fd5b506104a161174d565b34801561090557600080fd5b506105cb7f4ebb3eb1732de51e78148107b1735f1eb406c54fc4634032f37c85769c2b55b981565b34801561093957600080fd5b506104a16109483660046146e2565b611761565b34801561095957600080fd5b506104a16109683660046144ad565b6117d7565b34801561097957600080fd5b506105cb6118c6565b34801561098e57600080fd5b506104a161099d36600461465d565b6118e8565b3480156109ae57600080fd5b506005546001600160a01b03165b6040516001600160a01b039091168152602001610483565b3480156109e057600080fd5b506109bc6109ef366004614699565b61198b565b348015610a0057600080fd5b50610477610a0f366004614675565b6119a3565b348015610a2057600080fd5b506104f86119ce565b348015610a3557600080fd5b5061051a6119dd565b348015610a4a57600080fd5b506105cb600081565b348015610a5f57600080fd5b50610477610a6e36600461458a565b611a0f565b348015610a7f57600080fd5b506105cb600f5481565b348015610a9557600080fd5b50610477610aa43660046144ad565b602b6020526000908152604090205460ff1681565b348015610ac557600080fd5b50610477610ad436600461458a565b611a95565b348015610ae557600080fd5b506104a1610af43660046144e5565b611aa3565b348015610b0557600080fd5b506104a1610b14366004614625565b611ad1565b348015610b2557600080fd5b506104a1610b343660046144ad565b611b48565b348015610b4557600080fd5b506104a1611b69565b348015610b5a57600080fd5b506104a1610b69366004614625565b611bd5565b348015610b7a57600080fd5b506104a1610b8936600461465d565b611c36565b348015610b9a57600080fd5b506104a1611cc2565b348015610baf57600080fd5b506105cb610bbe36600461465d565b611d22565b348015610bcf57600080fd5b506104a1610bde3660046144ad565b611d39565b348015610bef57600080fd5b506104a1610bfe36600461465d565b611d7b565b348015610c0f57600080fd5b50600e546109bc906001600160a01b031681565b348015610c2f57600080fd5b506104a1610c3e36600461465d565b611e87565b348015610c4f57600080fd5b506104a1610c5e366004614675565b611f6d565b348015610c6f57600080fd5b506023546104779060ff1681565b348015610c8957600080fd5b506105cb610c983660046144e5565b611f92565b348015610ca957600080fd5b506104a1610cb836600461465d565b611fbd565b348015610cc957600080fd5b506104a1610cd836600461465d565b61205c565b348015610ce957600080fd5b506104a1610cf836600461455d565b61212a565b348015610d0957600080fd5b506104a1610d18366004614625565b61216e565b348015610d2957600080fd5b506104a1610d3836600461465d565b61219a565b348015610d4957600080fd5b50602354610477906301000000900460ff1681565b348015610d6a57600080fd5b506105cb600080516020614b1183398151915281565b348015610d8c57600080fd5b506104a1610d9b3660046144ad565b61221c565b348015610dac57600080fd5b506104a1610dbb3660046145b5565b612292565b348015610dcc57600080fd5b50610477610ddb3660046144ad565b6001600160a01b03166000908152600b602052604090205460ff1690565b348015610e0557600080fd5b5060235461047790610100900460ff1681565b348015610e2457600080fd5b506104a1610e3336600461465d565b61232a565b60006001600160e01b03198216635a05180f60e01b1480610e5d5750610e5d8261243d565b92915050565b600080516020614b11833981519152610e7b81612472565b602954601154610e989130916001600160a01b039091169061247c565b6029546001600160a01b031663f305d7194730610eb481611732565b600080610ec96005546001600160a01b031690565b426040518863ffffffff1660e01b8152600401610eeb969594939291906147bc565b6060604051808303818588803b158015610f0457600080fd5b505af1158015610f18573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610f3d919061471a565b505050610f48611b69565b602a5460295460405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b390604401602060405180830381600087803b158015610f9957600080fd5b505af1158015610fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd19190614641565b5050565b600080516020614b11833981519152610fed81612472565b601c805463ff00000019166301000000841515810291909117918290556026546027546040805160ff949095049390931615158452602084019190915290820152600260608201527f9c7f888bfb9f4cac2c303d7608203c132c217df3cf2be1a6025ceae313ef0115906080015b60405180910390a15050565b600080516020614b1183398151915261107f81612472565b60008211801561109357506402540be40082105b6110d45760405162461bcd60e51b815260206004820152600d60248201526c484f4c4445525f4c494d49543160981b60448201526064015b60405180910390fd5b60006110e26012600a61493a565b6110ec9084614a08565b90506103e860115460056111009190614a08565b61110a91906148d4565b81116111485760405162461bcd60e51b815260206004820152600d60248201526c2427a62222a92fa624a6a4aa1960991b60448201526064016110cb565b6027819055601c5460265460408051630100000090930460ff161515835260208301919091528101829052600260608201527f9c7f888bfb9f4cac2c303d7608203c132c217df3cf2be1a6025ceae313ef01159060800160405180910390a1505050565b6060600380546111bb90614a81565b80601f01602080910402602001604051908101604052809291908181526020018280546111e790614a81565b80156112345780601f1061120957610100808354040283529160200191611234565b820191906000526020600020905b81548152906001019060200180831161121757829003601f168201915b5050505050905090565b6000806000600080516020614b1183398151915261125b81612472565b5050602654602754909390925060029150565b60003361127c81858561247c565b5060019392505050565b600080516020614b1183398151915261129e81612472565b50600d55565b600080516020614b118339815191526112bc81612472565b81156112db576112cc60016125a0565b6112d660006125a0565b610fd1565b6112e560016125da565b610fd160006125da565b600080516020614b1183398151915261130781612472565b81158061132d57506001600160a01b0383166000908152600c602052604090205460ff16155b6113625760405162461bcd60e51b8152602060048201526006602482015265424c53542d3160d01b60448201526064016110cb565b506001600160a01b03919091166000908152600b60205260409020805460ff1916911515919091179055565b600080516020614b118339815191526113a681612472565b6001600160a01b0382166113e55760405162461bcd60e51b81526004016110cb9060208082526004908201526352322d3160e01b604082015260600190565b610fd182612600565b600080516020614b1183398151915261140681612472565b5060238054911515620100000262ff000019909216919091179055565b600033611431858285612a67565b61143c858585612adb565b60019150505b9392505050565b600080516020614b1183398151915261146181612472565b61146b8383612c54565b505050565b60008281526006602052604090206001015461148b81612472565b61146b8383612c92565b6001600160a01b03811633146115055760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016110cb565b610fd18282612cb4565b60003361127c8185856115228383611f92565b61152c91906148bc565b61247c565b600080516020614b1183398151915261154981612472565b506001600160a01b03919091166000908152600a60205260409020805460ff1916911515919091179055565b600080516020614b1183398151915261158d81612472565b601c54610100900460ff16156115d55760405162461bcd60e51b815260206004820152600d60248201526c057495448445241572d5357415609c1b60448201526064016110cb565b600e546115f59030906001600160a01b03166115f082611732565b612cd6565b506000600f819055601055565b600080516020614b1183398151915261161a81612472565b81158061164057506001600160a01b0383166000908152600b602052604090205460ff16155b6116755760405162461bcd60e51b8152602060048201526006602482015265212629aa169960d11b60448201526064016110cb565b506001600160a01b03919091166000908152600c60205260409020805460ff1916911515919091179055565b600080516020614b118339815191526116b981612472565b6023805463ff000000191663010000008415158102919091179182905560405160ff9190920416151581527fd11ee79597d5e7d44812e295744bbd79e940bae6dbdf9c6d2722e5788e4b38199060200161105b565b600080821561172457505060145460155461172d565b50506018546019545b915091565b6001600160a01b031660009081526020819052604090205490565b611755612ea4565b61175f6000612efe565b565b600080516020614b1183398151915261177981612472565b606461178585856148bc565b11156117bd5760405162461bcd60e51b815260206004820152600760248201526608c8a8a5a9a82b60cb1b60448201526064016110cb565b6117c78383612f50565b6117d18483612faf565b50505050565b600080516020614b118339815191526117ef81612472565b6001600160a01b03821661182e5760405162461bcd60e51b81526020600482015260066024820152650414444522d360d41b60448201526064016110cb565b600047116118665760405162461bcd60e51b8152602060048201526005602482015264042414c2d360dc1b60448201526064016110cb565b60405147906000906001600160a01b0385169083908381818185875af1925050503d80600081146118b3576040519150601f19603f3d011682016040523d82523d6000602084013e6118b8565b606091505b50509050806117d157600080fd5b6000600080516020614b118339815191526118e081612472565b505060285490565b600080516020614b1183398151915261190081612472565b600082116119415760405162461bcd60e51b815260206004820152600e60248201526d04150532d494e54455256414c2d360941b60448201526064016110cb565b6022829055601c5460215460208054604080516201000090950460ff16151585529184019290925282015260608101839052600080516020614b318339815191529060800161105b565b6000828152600760205260408120611442908361300e565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060600480546111bb90614a81565b6000806000600080516020614b118339815191526119fa81612472565b60215460205460225493509350935050909192565b60003381611a1d8286611f92565b905083811015611a7d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016110cb565b611a8a828686840361247c565b506001949350505050565b60003361127c818585612adb565b600080516020614b11833981519152611abb81612472565b611ac683600161301a565b61146b82600161301a565b600080516020614b11833981519152611ae981612472565b601c805462ff000019166201000084151581029190911791829055602154602080546022546040805160ff96909704959095161515865291850192909252918301526060820152600080516020614b318339815191529060800161105b565b600080516020614b11833981519152611b6081612472565b610fd182613058565b600080516020614b11833981519152611b8181612472565b6023805460ff1916600190811790915560408051918252600060208301819052908201527f20851fa0422d4f14abd10a67c93b0b65e055acfea35fd9d08e4c2489f6ed0d4f9060600160405180910390a150565b600080516020614b11833981519152611bed81612472565b601c80548315156101000261ff00199091161790556040517f53726dfcaf90650aa7eb35524f4d3220f07413c8d6cb404cc8c18bf5591bc1599061105b90841515815260200190565b600080516020614b11833981519152611c4e81612472565b6000611c5c6012600a61493a565b611c669084614a08565b9050611c746012600a61493a565b611c80906103e8614a08565b8111611cbb5760405162461bcd60e51b815260206004820152600a6024820152695448524553482d4c4f5760b01b60448201526064016110cb565b6028555050565b600080516020614b11833981519152611cda81612472565b60235460ff16611d175760405162461bcd60e51b81526020600482015260086024820152674c49512d4e4f4e4560c01b60448201526064016110cb565b611d1f6130d4565b50565b6000818152600760205260408120610e5d90613126565b7f4ebb3eb1732de51e78148107b1735f1eb406c54fc4634032f37c85769c2b55b9611d6381612472565b610fd1600080516020614b1183398151915283611470565b600080516020614b11833981519152611d9381612472565b60018211611dd15760405162461bcd60e51b815260206004820152600b60248201526a5748542d4455522d4c4f5760a81b60448201526064016110cb565b601c805464ff000000001916640100000000179055601e82905542601d55611dfb6012600a61493a565b611e09906301312d00614a08565b6026556023805461ff0019169055604080516001808252602082015260008183015290517f20851fa0422d4f14abd10a67c93b0b65e055acfea35fd9d08e4c2489f6ed0d4f9181900360600190a16040518281527fc7addf6b620f1a592cf9dc47508c92f3cf36054d8b77393f7a90a23ef960acb39060200161105b565b600080516020614b11833981519152611e9f81612472565b600082118015611eaf5750606482105b611eee5760405162461bcd60e51b815260206004820152601060248201526f135056151617d4115490d7d31253525560821b60448201526064016110cb565b611f0f6103e8611f098460115461313090919063ffffffff16565b9061313c565b6026819055601c5460275460408051630100000090930460ff1615158352602083019390935291810191909152600260608201527f9c7f888bfb9f4cac2c303d7608203c132c217df3cf2be1a6025ceae313ef01159060800161105b565b600082815260066020526040902060010154611f8881612472565b61146b8383612cb4565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600080516020614b11833981519152611fd581612472565b601482106120145760405162461bcd60e51b815260206004820152600c60248201526b105414cb55160b531253525560a21b60448201526064016110cb565b6021829055601c5460208054602254604080516201000090950460ff1615158552928401869052918301526060820152600080516020614b318339815191529060800161105b565b600080516020614b1183398151915261207481612472565b6103e88211801561208957506402540be40082105b6120c95760405162461bcd60e51b8152602060048201526011602482015270105414cb5512149154d20b505353d55395607a1b60448201526064016110cb565b6120d56012600a61493a565b6120df9083614a08565b6020818155601c54602154602254604080516201000090940460ff161515845293830191909152918101929092526060820152600080516020614b318339815191529060800161105b565b600080516020614b1183398151915261214281612472565b506001600160a01b03919091166000908152600960205260409020805460ff1916911515919091179055565b600080516020614b1183398151915261218681612472565b50601f805460ff1916911515919091179055565b600080516020614b118339815191526121b281612472565b600182101580156121c757506402540be40082105b6122065760405162461bcd60e51b815260206004820152601060248201526f135056151617d053539517d31253525560821b60448201526064016110cb565b6122126012600a61493a565b611f0f9083614a08565b612224612ea4565b6001600160a01b0381166122895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016110cb565b611d1f81612efe565b600080516020614b118339815191526122aa81612472565b60005b828110156117d1576001600c60008686858181106122db57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906122f091906144ad565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558061232281614abc565b9150506122ad565b600080516020614b1183398151915261234281612472565b603282106123875760405162461bcd60e51b8152602060048201526012602482015271105414cb5512149154d20b54115490d1539560721b60448201526064016110cb565b6120df6103e8611f098460115461313090919063ffffffff16565b6123ac82826119a3565b610fd15760008281526006602090815260408083206001600160a01b03851684529091529020805460ff191660011790556123e43390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000611442836001600160a01b038416613148565b60006001600160e01b03198216637965db0b60e01b1480610e5d57506301ffc9a760e01b6001600160e01b0319831614610e5d565b611d1f8133613197565b6001600160a01b0383166124de5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016110cb565b6001600160a01b03821661253f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016110cb565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b80156125c15760148054601655601580546017556000908190559055611d1f565b60188054601a5560198054601b55600090819055905550565b80156125f157601654601455601754601555611d1f565b601a54601855601b5460195550565b602980546001600160a01b0319166001600160a01b0383169081179091556040805163c45a015560e01b8152905163c45a015591600480820192602092909190829003018186803b15801561265457600080fd5b505afa158015612668573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268c91906144c9565b6001600160a01b031663c9c6539630602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b1580156126e957600080fd5b505afa1580156126fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272191906144c9565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381600087803b15801561276957600080fd5b505af115801561277d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127a191906144c9565b602a80546001600160a01b0319166001600160a01b039290921691821790556127cb906001612c54565b6029546001600160a01b03166000908152600a60205260409020805460ff191660011790556128196128056005546001600160a01b031690565b6029546001600160a01b031660001961247c565b602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b15801561286757600080fd5b505afa15801561287b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289f91906144c9565b60295460405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b390604401602060405180830381600087803b1580156128ed57600080fd5b505af1158015612901573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129259190614641565b50602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b15801561297457600080fd5b505afa158015612988573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ac91906144c9565b60405163095ea7b360e01b815230600482015260001960248201526001600160a01b03919091169063095ea7b390604401602060405180830381600087803b1580156129f757600080fd5b505af1158015612a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2f9190614641565b506040516001600160a01b038216907f7e336871192a11cf6144610c966672324a2721225248a567fd1211203248469e90600090a250565b6000612a738484611f92565b905060001981146117d15781811015612ace5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016110cb565b6117d1848484840361247c565b6001600160a01b038316612b1f5760405162461bcd60e51b815260206004820152600b60248201526a046524f4d2d414444522d360ac1b60448201526064016110cb565b6001600160a01b038216612b615760405162461bcd60e51b81526020600482015260096024820152680544f2d414444522d360bc1b60448201526064016110cb565b80612b7757612b7283836000612cd6565b61146b565b6001600160a01b0383166000908152600b602052604090205460ff1680612bb657506001600160a01b0382166000908152600b602052604090205460ff165b15612bc657612b728383836131fb565b601c5460ff16612bf857612bd8613367565b612be38383836133d0565b612bee8383836136ed565b612bf88383613832565b601c546001600160a01b03841660009081526009602052604090205460ff91821615911680612c3f57506001600160a01b03831660009081526009602052604090205460ff165b15612c48575060005b6117d1848484846138d0565b6001600160a01b039091166000908152602b60209081526040808320805494151560ff199586168117909155600a9092529091208054909216179055565b612c9c82826123a2565b600082815260076020526040902061146b9082612428565b612cbe8282613a2f565b600082815260076020526040902061146b9082613a96565b6001600160a01b038316612d3a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016110cb565b6001600160a01b038216612d9c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016110cb565b6001600160a01b03831660009081526020819052604090205481811015612e145760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016110cb565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290612e4b9084906148bc565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612e9791815260200190565b60405180910390a36117d1565b6005546001600160a01b0316331461175f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016110cb565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b603c821115612f8f5760405162461bcd60e51b815260206004820152600b60248201526a4645452d4c494d49542d4d60a81b60448201526064016110cb565b8015612fa45760148054601655829055610fd1565b5060188054601a5555565b603c821115612fee5760405162461bcd60e51b815260206004820152600b60248201526a1191514b53125352550b5360aa1b60448201526064016110cb565b80156130035760158054601755829055610fd1565b5060198054601b5555565b60006114428383613aab565b6001600160a01b039091166000908152600960209081526040808320805494151560ff199586168117909155600a9092529091208054909216179055565b6001600160a01b0381166130975760405162461bcd60e51b81526020600482015260066024820152650414444522d360d41b60448201526064016110cb565b600e546130ae906001600160a01b0316600061301a565b600e80546001600160a01b0319166001600160a01b038316179055611d1f81600161301a565b6023805461ff001916610100179055604080516001808252602082018190528183015290517f20851fa0422d4f14abd10a67c93b0b65e055acfea35fd9d08e4c2489f6ed0d4f916060908290030190a1565b6000610e5d825490565b60006114428284614a08565b600061144282846148d4565b600081815260018301602052604081205461318f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610e5d565b506000610e5d565b6131a182826119a3565b610fd1576131b9816001600160a01b03166014613ae3565b6131c4836020613ae3565b6040516020016131d5929190614747565b60408051601f198184030181529082905262461bcd60e51b82526110cb916004016147f7565b60006103e8600d548361320e9190614a08565b61321891906148d4565b905060006132268284614a27565b9050613233853084612cd6565b61323e858583612cd6565b600080600061324c88613cc5565b156132a45760145460155461326191906148bc565b9250821561329f57601554613277576000613290565b60155483906132869087614a08565b61329091906148d4565b905061329c8186614a27565b91505b6132f2565b6018546019546132b491906148bc565b925082156132f2576019546132ca5760006132e3565b60195483906132d99087614a08565b6132e391906148d4565b90506132ef8186614a27565b91505b821561335d5781600f600082825461330a91906148bc565b92505081905550806010600082825461332391906148bc565b90915550506012805483919060009061333d9084906148bc565b9091555050601380548291906000906133579084906148bc565b90915550505b5050505050505050565b601c54640100000000900460ff161561175f5742601e54603c61338a9190614a08565b601d5461339791906148bc565b101561175f57601c805464ff00000000191690556133b76012600a61493a565b6133c5906301c9c380614a08565b60265561175f6130d4565b601c546301000000900460ff161561146b576133ed838383613ce3565b601c54640100000000900460ff16158061344457506001600160a01b0383166000908152600c602052604090205460ff1615801561344457506001600160a01b0382166000908152600c602052604090205460ff16155b156134ec57602354610100900460ff1661348c5760405162461bcd60e51b81526020600482015260096024820152685443532d545241444560b81b60448201526064016110cb565b601f5460ff16806134a157506134a183613cc5565b806134b057506134b082613cc5565b6134ec5760405162461bcd60e51b815260206004820152600d60248201526c5443532d4143432d534841524560981b60448201526064016110cb565b6134f583613cc5565b156135565760275461350683611732565b61351090836148bc565b11156135515760405162461bcd60e51b815260206004820152601060248201526f1510d4cb5213d31111548b531253525560821b60448201526064016110cb565b6135ba565b61355f82613cc5565b6135ba5760275461356f83611732565b61357990836148bc565b11156135ba5760405162461bcd60e51b815260206004820152601060248201526f1510d4cb5213d31111548b531253525560821b60448201526064016110cb565b6135c382613cc5565b1561361557426135d56002603c614a08565b6001600160a01b0385166000908152602460205260409020546135f891906148bc565b10612b725760405162461bcd60e51b81526004016110cb9061482a565b61361e83613cc5565b1561365357426136306002603c614a08565b6001600160a01b0384166000908152602560205260409020546135f891906148bc565b426136606002603c614a08565b6001600160a01b03851660009081526024602052604090205461368391906148bc565b106136a05760405162461bcd60e51b81526004016110cb9061482a565b426136ad6002603c614a08565b6001600160a01b0384166000908152602560205260409020546136d091906148bc565b1061146b5760405162461bcd60e51b81526004016110cb9061482a565b601c5462010000900460ff161561146b576103e860215461370d60025490565b6137179190614a08565b61372191906148d4565b811061375c5760405162461bcd60e51b815260206004820152600a6024820152694150532d535550504c5960b01b60448201526064016110cb565b61376582613cc5565b1561146b57600061377584611732565b905060205481106137c75761378b6005826148d4565b82106137c75760405162461bcd60e51b815260206004820152600b60248201526a4150532d42414c414e434560a81b60448201526064016110cb565b42602254603c6137d79190614a08565b6001600160a01b0386166000908152602460205260409020546137fa91906148bc565b106117d15760405162461bcd60e51b81526020600482015260086024820152674150532d54494d4560c01b60448201526064016110cb565b601c5460ff1615801561384b575061384982613cc5565b155b801561385e5750601c54610100900460ff165b801561388357506001600160a01b03821660009081526009602052604090205460ff16155b80156138a857506001600160a01b03811660009081526009602052604090205460ff16155b15610fd157601c805460ff191660011790556138c2613e4b565b601c805460ff191690555050565b60006138db85613cc5565b9050600082156139995760006138f18584614033565b90508060600151816040015161390791906148bc565b91508115613997578060400151600f600082825461392591906148bc565b90915550506060810151601080546000906139419084906148bc565b909155505060408101516012805460009061395d9084906148bc565b90915550506060810151601380546000906139799084906148bc565b9091555061398a9050873084612cd6565b6139948286614a27565b94505b505b81156139bf576001600160a01b0385166000908152602560205260409020429055613a1c565b6139c885613cc5565b156139ed576001600160a01b0386166000908152602460205260409020429055613a1c565b6001600160a01b0380861660009081526025602090815260408083204290819055938a16835260249091529020555b613a27868686612cd6565b505050505050565b613a3982826119a3565b15610fd15760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000611442836001600160a01b0384166140a7565b6000826000018281548110613ad057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60606000613af2836002614a08565b613afd9060026148bc565b67ffffffffffffffff811115613b2357634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613b4d576020820181803683370190505b509050600360fc1b81600081518110613b7657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613bb357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000613bd7846002614a08565b613be29060016148bc565b90505b6001811115613c76576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613c2457634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110613c4857634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93613c6f81614a6a565b9050613be5565b5083156114425760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016110cb565b6001600160a01b03166000908152602b602052604090205460ff1690565b613cec83613cc5565b15613d555760265481111580613d1a57506001600160a01b0382166000908152600a602052604090205460ff165b612b725760405162461bcd60e51b815260206004820152600c60248201526b54582d4c494d49542d42555960a01b60448201526064016110cb565b613d5e82613cc5565b15613dc85760265481111580613d8c57506001600160a01b0383166000908152600a602052604090205460ff165b612b725760405162461bcd60e51b815260206004820152600d60248201526c15160b53125352550b54d15313609a1b60448201526064016110cb565b60265481111580613e1457506001600160a01b0383166000908152600a602052604090205460ff168015613e1457506001600160a01b0382166000908152600a602052604090205460ff165b61146b5760405162461bcd60e51b815260206004820152600860248201526715160b531253525560c21b60448201526064016110cb565b6000613e5630611732565b90506000600f54601054613e6a91906148bc565b9050811580613e77575080155b80613e83575060285481105b15613e8f57505061175f565b600060028260105485613ea29190614a08565b613eac91906148d4565b613eb691906148d4565b90506000613ec484836141c4565b905047613ed182306141d0565b6000613edd47836141c4565b90506000613efa86611f09600f548561313090919063ffffffff16565b90506000613f088284614a27565b90506000601054118015613f1c5750600081115b15613f8257613f2b8682614356565b7f17bbfb9a6069321b6ded73bd96327c9e6b7212a5cd51ff219cd61370acafb5618682613f63896010546141c490919063ffffffff16565b6040805193845260208401929092529082015260600160405180910390a15b600e546040516000916001600160a01b03169084908381818185875af1925050503d8060008114613fcf576040519150601f19603f3d011682016040523d82523d6000602084013e613fd4565b606091505b5050600f546040805191825260208201869052821515908201529091507fe4b0471ec14ebebbb513d957de87fec57e9abdbdf15f1afedcce783601dd89189060600160405180910390a1505060006010819055600f5550505050505050565b61405e6040518060800160405280600081526020016000815260200160008152602001600081525090565b82815261406b8383614406565b604082015261407a838361445d565b60608201819052604082015161409c91906140969086906141c4565b906141c4565b602082015292915050565b600081815260018301602052604081205480156141ba5760006140cb600183614a27565b85549091506000906140df90600190614a27565b905081811461416057600086600001828154811061410d57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061413e57634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061417f57634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610e5d565b6000915050610e5d565b60006114428284614a27565b604080516002808252606082018352600092602083019080368337019050509050308160008151811061421357634e487b7160e01b600052603260045260246000fd5b6001600160a01b03928316602091820292909201810191909152602954604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561426757600080fd5b505afa15801561427b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061429f91906144c9565b816001815181106142c057634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526029546142e6913091168561247c565b60295460405163791ac94760e01b81526001600160a01b039091169063791ac9479061431f90869060009086908890429060040161484c565b600060405180830381600087803b15801561433957600080fd5b505af115801561434d573d6000803e3d6000fd5b50505050505050565b60295461436e9030906001600160a01b03168461247c565b60295460405163f305d71960e01b81526001600160a01b039091169063f305d7199083906143ad9030908790600090819061dead9042906004016147bc565b6060604051808303818588803b1580156143c657600080fd5b505af11580156143da573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906143ff919061471a565b5050505050565b600081156144395760145461441c576000614432565b601454614432906103e890611f09908690613130565b9050610e5d565b601854614447576000614432565b601854614432906103e890611f09908690613130565b6000811561448957601554614473576000614432565b601554614432906103e890611f09908690613130565b601954614497576000614432565b601954614432906103e890611f09908690613130565b6000602082840312156144be578081fd5b813561144281614aed565b6000602082840312156144da578081fd5b815161144281614aed565b600080604083850312156144f7578081fd5b823561450281614aed565b9150602083013561451281614aed565b809150509250929050565b600080600060608486031215614531578081fd5b833561453c81614aed565b9250602084013561454c81614aed565b929592945050506040919091013590565b6000806040838503121561456f578182fd5b823561457a81614aed565b9150602083013561451281614b02565b6000806040838503121561459c578182fd5b82356145a781614aed565b946020939093013593505050565b600080602083850312156145c7578182fd5b823567ffffffffffffffff808211156145de578384fd5b818501915085601f8301126145f1578384fd5b8135818111156145ff578485fd5b8660208260051b8501011115614613578485fd5b60209290920196919550909350505050565b600060208284031215614636578081fd5b813561144281614b02565b600060208284031215614652578081fd5b815161144281614b02565b60006020828403121561466e578081fd5b5035919050565b60008060408385031215614687578182fd5b82359150602083013561451281614aed565b600080604083850312156146ab578182fd5b50508035926020909101359150565b6000602082840312156146cb578081fd5b81356001600160e01b031981168114611442578182fd5b6000806000606084860312156146f6578081fd5b8335925060208401359150604084013561470f81614b02565b809150509250925092565b60008060006060848603121561472e578081fd5b8351925060208401519150604084015190509250925092565b60007f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008252835161477f816017850160208801614a3e565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516147b0816028840160208801614a3e565b01602801949350505050565b6001600160a01b039687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b6000602082528251806020840152614816816040850160208701614a3e565b601f01601f19169190910160400192915050565b6020808252600890820152675443532d54494d4560c01b604082015260600190565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b8181101561489b5784516001600160a01b031683529383019391830191600101614876565b50506001600160a01b03969096166060850152505050608001529392505050565b600082198211156148cf576148cf614ad7565b500190565b6000826148ef57634e487b7160e01b81526012600452602481fd5b500490565b80825b60018086116149065750614931565b81870482111561491857614918614ad7565b8086161561492557918102915b9490941c9380026148f7565b94509492505050565b6000611442600019848460008261495357506001611442565b8161496057506000611442565b81600181146149765760028114614980576149ad565b6001915050611442565b60ff84111561499157614991614ad7565b6001841b9150848211156149a7576149a7614ad7565b50611442565b5060208310610133831016604e8410600b84101617156149e0575081810a838111156149db576149db614ad7565b611442565b6149ed84848460016148f4565b8086048211156149ff576149ff614ad7565b02949350505050565b6000816000190483118215151615614a2257614a22614ad7565b500290565b600082821015614a3957614a39614ad7565b500390565b60005b83811015614a59578181015183820152602001614a41565b838111156117d15750506000910152565b600081614a7957614a79614ad7565b506000190190565b600181811c90821680614a9557607f821691505b60208210811415614ab657634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614ad057614ad0614ad7565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114611d1f57600080fd5b8015158114611d1f57600080fdfee33cade2d66e04fd0493fc676b10225974e8a5e7a703b4ffe78a5b4509bff0b98ee018fc6d9be726281c70ad01c6b66e2029e32016d05bc754dbf909b362bb55a2646970667358221220de5a14271d51ac94baafa93df62bdd5e0add6149d816bd4a508ff9aaed5c740764736f6c634300080300334ebb3eb1732de51e78148107b1735f1eb406c54fc4634032f37c85769c2b55b9e33cade2d66e04fd0493fc676b10225974e8a5e7a703b4ffe78a5b4509bff0b9

Deployed Bytecode

0x60806040526004361061044b5760003560e01c80638cab3a6611610234578063cc6c914f1161012e578063e720c7eb116100b6578063f2fde38b1161007a578063f2fde38b14610d80578063f73b554114610da0578063fe575a8714610dc0578063ffb54a9914610df9578063ffbd7b3a14610e1857610452565b8063e720c7eb14610cdd578063eae9bdb714610cfd578063ec28438a14610d1d578063ee294a1b14610d3d578063ee88ac8e14610d5e57610452565b8063d547741f116100fd578063d547741f14610c43578063d944392314610c63578063dd62ed3e14610c7d578063de74407114610c9d578063e1a4206714610cbd57610452565b8063cc6c914f14610bc3578063cd2cd9e414610be3578063d158272d14610c03578063d543dbeb14610c2357610452565b8063a72905a2116101bc578063bbeb5db011610180578063bbeb5db014610b39578063c49b9a8014610b4e578063c8125a7814610b6e578063c9567bf914610b8e578063ca15c87314610ba357610452565b8063a72905a214610a89578063a9059cbb14610ab9578063b743d07214610ad9578063bb095b9b14610af9578063bb85c6d114610b1957610452565b806395d89b411161020357806395d89b4114610a14578063a15af6f714610a29578063a217fddf14610a3e578063a457c2d714610a53578063a5f2aba514610a7357610452565b80638cab3a66146109825780638da5cb5b146109a25780639010d07c146109d457806391d14854146109f457610452565b8063313ce567116103455780635738047a116102cd578063715018a611610291578063715018a6146108e4578063753643c5146108f9578063761ce8411461092d5780637ac0d1551461094d57806388ffe7db1461096d57610452565b80635738047a1461082b578063658c27a91461084b578063665e3728146108845780636f44902f146108a457806370a08231146108c457610452565b80633b25f85c116103145780633b25f85c1461077c578063476343ee1461079c5780634ccf15ef146107b15780635342acb4146107d257806353d6fd591461080b57610452565b8063313ce567146106e757806336568abe1461070357806339509351146107235780633af32abf1461074357610452565b8063153b0d1e116103d35780631bd96bd6116103975780631bd96bd61461062e57806323b872dd14610657578063248a9ca3146106775780632d99d32e146106a75780632f2ff15d146106c757610452565b8063153b0d1e14610595578063165f16d0146105b557806318160ddd146105d957806319d659b5146105ee5780631b7852181461060e57610452565b806306fdde031161041a57806306fdde03146104e357806309552a3114610505578063095ea7b3146105355780630a7c0163146105555780630d95ccc91461057557610452565b806301ffc9a7146104575780630210a83d1461048c57806304046287146104a357806306f91d59146104c357610452565b3661045257005b600080fd5b34801561046357600080fd5b506104776104723660046146ba565b610e38565b60405190151581526020015b60405180910390f35b34801561049857600080fd5b506104a1610e63565b005b3480156104af57600080fd5b506104a16104be366004614625565b610fd5565b3480156104cf57600080fd5b506104a16104de36600461465d565b611067565b3480156104ef57600080fd5b506104f86111ac565b60405161048391906147f7565b34801561051157600080fd5b5061051a61123e565b60408051938452602084019290925290820152606001610483565b34801561054157600080fd5b5061047761055036600461458a565b61126e565b34801561056157600080fd5b506104a161057036600461465d565b611286565b34801561058157600080fd5b506104a1610590366004614625565b6112a4565b3480156105a157600080fd5b506104a16105b036600461455d565b6112ef565b3480156105c157600080fd5b506105cb60105481565b604051908152602001610483565b3480156105e557600080fd5b506002546105cb565b3480156105fa57600080fd5b506104a16106093660046144ad565b61138e565b34801561061a57600080fd5b506104a1610629366004614625565b6113ee565b34801561063a57600080fd5b506012546013545b60408051928352602083019190915201610483565b34801561066357600080fd5b5061047761067236600461451d565b611423565b34801561068357600080fd5b506105cb61069236600461465d565b60009081526006602052604090206001015490565b3480156106b357600080fd5b506104a16106c236600461455d565b611449565b3480156106d357600080fd5b506104a16106e2366004614675565b611470565b3480156106f357600080fd5b5060405160128152602001610483565b34801561070f57600080fd5b506104a161071e366004614675565b611495565b34801561072f57600080fd5b5061047761073e36600461458a565b61150f565b34801561074f57600080fd5b5061047761075e3660046144ad565b6001600160a01b03166000908152600c602052604090205460ff1690565b34801561078857600080fd5b506104a161079736600461455d565b611531565b3480156107a857600080fd5b506104a1611575565b3480156107bd57600080fd5b50601c54610477906301000000900460ff1681565b3480156107de57600080fd5b506104776107ed3660046144ad565b6001600160a01b031660009081526009602052604090205460ff1690565b34801561081757600080fd5b506104a161082636600461455d565b611602565b34801561083757600080fd5b50601c546104779062010000900460ff1681565b34801561085757600080fd5b506104776108663660046144ad565b6001600160a01b03166000908152600a602052604090205460ff1690565b34801561089057600080fd5b506104a161089f366004614625565b6116a1565b3480156108b057600080fd5b506106426108bf366004614625565b61170e565b3480156108d057600080fd5b506105cb6108df3660046144ad565b611732565b3480156108f057600080fd5b506104a161174d565b34801561090557600080fd5b506105cb7f4ebb3eb1732de51e78148107b1735f1eb406c54fc4634032f37c85769c2b55b981565b34801561093957600080fd5b506104a16109483660046146e2565b611761565b34801561095957600080fd5b506104a16109683660046144ad565b6117d7565b34801561097957600080fd5b506105cb6118c6565b34801561098e57600080fd5b506104a161099d36600461465d565b6118e8565b3480156109ae57600080fd5b506005546001600160a01b03165b6040516001600160a01b039091168152602001610483565b3480156109e057600080fd5b506109bc6109ef366004614699565b61198b565b348015610a0057600080fd5b50610477610a0f366004614675565b6119a3565b348015610a2057600080fd5b506104f86119ce565b348015610a3557600080fd5b5061051a6119dd565b348015610a4a57600080fd5b506105cb600081565b348015610a5f57600080fd5b50610477610a6e36600461458a565b611a0f565b348015610a7f57600080fd5b506105cb600f5481565b348015610a9557600080fd5b50610477610aa43660046144ad565b602b6020526000908152604090205460ff1681565b348015610ac557600080fd5b50610477610ad436600461458a565b611a95565b348015610ae557600080fd5b506104a1610af43660046144e5565b611aa3565b348015610b0557600080fd5b506104a1610b14366004614625565b611ad1565b348015610b2557600080fd5b506104a1610b343660046144ad565b611b48565b348015610b4557600080fd5b506104a1611b69565b348015610b5a57600080fd5b506104a1610b69366004614625565b611bd5565b348015610b7a57600080fd5b506104a1610b8936600461465d565b611c36565b348015610b9a57600080fd5b506104a1611cc2565b348015610baf57600080fd5b506105cb610bbe36600461465d565b611d22565b348015610bcf57600080fd5b506104a1610bde3660046144ad565b611d39565b348015610bef57600080fd5b506104a1610bfe36600461465d565b611d7b565b348015610c0f57600080fd5b50600e546109bc906001600160a01b031681565b348015610c2f57600080fd5b506104a1610c3e36600461465d565b611e87565b348015610c4f57600080fd5b506104a1610c5e366004614675565b611f6d565b348015610c6f57600080fd5b506023546104779060ff1681565b348015610c8957600080fd5b506105cb610c983660046144e5565b611f92565b348015610ca957600080fd5b506104a1610cb836600461465d565b611fbd565b348015610cc957600080fd5b506104a1610cd836600461465d565b61205c565b348015610ce957600080fd5b506104a1610cf836600461455d565b61212a565b348015610d0957600080fd5b506104a1610d18366004614625565b61216e565b348015610d2957600080fd5b506104a1610d3836600461465d565b61219a565b348015610d4957600080fd5b50602354610477906301000000900460ff1681565b348015610d6a57600080fd5b506105cb600080516020614b1183398151915281565b348015610d8c57600080fd5b506104a1610d9b3660046144ad565b61221c565b348015610dac57600080fd5b506104a1610dbb3660046145b5565b612292565b348015610dcc57600080fd5b50610477610ddb3660046144ad565b6001600160a01b03166000908152600b602052604090205460ff1690565b348015610e0557600080fd5b5060235461047790610100900460ff1681565b348015610e2457600080fd5b506104a1610e3336600461465d565b61232a565b60006001600160e01b03198216635a05180f60e01b1480610e5d5750610e5d8261243d565b92915050565b600080516020614b11833981519152610e7b81612472565b602954601154610e989130916001600160a01b039091169061247c565b6029546001600160a01b031663f305d7194730610eb481611732565b600080610ec96005546001600160a01b031690565b426040518863ffffffff1660e01b8152600401610eeb969594939291906147bc565b6060604051808303818588803b158015610f0457600080fd5b505af1158015610f18573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610f3d919061471a565b505050610f48611b69565b602a5460295460405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b390604401602060405180830381600087803b158015610f9957600080fd5b505af1158015610fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd19190614641565b5050565b600080516020614b11833981519152610fed81612472565b601c805463ff00000019166301000000841515810291909117918290556026546027546040805160ff949095049390931615158452602084019190915290820152600260608201527f9c7f888bfb9f4cac2c303d7608203c132c217df3cf2be1a6025ceae313ef0115906080015b60405180910390a15050565b600080516020614b1183398151915261107f81612472565b60008211801561109357506402540be40082105b6110d45760405162461bcd60e51b815260206004820152600d60248201526c484f4c4445525f4c494d49543160981b60448201526064015b60405180910390fd5b60006110e26012600a61493a565b6110ec9084614a08565b90506103e860115460056111009190614a08565b61110a91906148d4565b81116111485760405162461bcd60e51b815260206004820152600d60248201526c2427a62222a92fa624a6a4aa1960991b60448201526064016110cb565b6027819055601c5460265460408051630100000090930460ff161515835260208301919091528101829052600260608201527f9c7f888bfb9f4cac2c303d7608203c132c217df3cf2be1a6025ceae313ef01159060800160405180910390a1505050565b6060600380546111bb90614a81565b80601f01602080910402602001604051908101604052809291908181526020018280546111e790614a81565b80156112345780601f1061120957610100808354040283529160200191611234565b820191906000526020600020905b81548152906001019060200180831161121757829003601f168201915b5050505050905090565b6000806000600080516020614b1183398151915261125b81612472565b5050602654602754909390925060029150565b60003361127c81858561247c565b5060019392505050565b600080516020614b1183398151915261129e81612472565b50600d55565b600080516020614b118339815191526112bc81612472565b81156112db576112cc60016125a0565b6112d660006125a0565b610fd1565b6112e560016125da565b610fd160006125da565b600080516020614b1183398151915261130781612472565b81158061132d57506001600160a01b0383166000908152600c602052604090205460ff16155b6113625760405162461bcd60e51b8152602060048201526006602482015265424c53542d3160d01b60448201526064016110cb565b506001600160a01b03919091166000908152600b60205260409020805460ff1916911515919091179055565b600080516020614b118339815191526113a681612472565b6001600160a01b0382166113e55760405162461bcd60e51b81526004016110cb9060208082526004908201526352322d3160e01b604082015260600190565b610fd182612600565b600080516020614b1183398151915261140681612472565b5060238054911515620100000262ff000019909216919091179055565b600033611431858285612a67565b61143c858585612adb565b60019150505b9392505050565b600080516020614b1183398151915261146181612472565b61146b8383612c54565b505050565b60008281526006602052604090206001015461148b81612472565b61146b8383612c92565b6001600160a01b03811633146115055760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016110cb565b610fd18282612cb4565b60003361127c8185856115228383611f92565b61152c91906148bc565b61247c565b600080516020614b1183398151915261154981612472565b506001600160a01b03919091166000908152600a60205260409020805460ff1916911515919091179055565b600080516020614b1183398151915261158d81612472565b601c54610100900460ff16156115d55760405162461bcd60e51b815260206004820152600d60248201526c057495448445241572d5357415609c1b60448201526064016110cb565b600e546115f59030906001600160a01b03166115f082611732565b612cd6565b506000600f819055601055565b600080516020614b1183398151915261161a81612472565b81158061164057506001600160a01b0383166000908152600b602052604090205460ff16155b6116755760405162461bcd60e51b8152602060048201526006602482015265212629aa169960d11b60448201526064016110cb565b506001600160a01b03919091166000908152600c60205260409020805460ff1916911515919091179055565b600080516020614b118339815191526116b981612472565b6023805463ff000000191663010000008415158102919091179182905560405160ff9190920416151581527fd11ee79597d5e7d44812e295744bbd79e940bae6dbdf9c6d2722e5788e4b38199060200161105b565b600080821561172457505060145460155461172d565b50506018546019545b915091565b6001600160a01b031660009081526020819052604090205490565b611755612ea4565b61175f6000612efe565b565b600080516020614b1183398151915261177981612472565b606461178585856148bc565b11156117bd5760405162461bcd60e51b815260206004820152600760248201526608c8a8a5a9a82b60cb1b60448201526064016110cb565b6117c78383612f50565b6117d18483612faf565b50505050565b600080516020614b118339815191526117ef81612472565b6001600160a01b03821661182e5760405162461bcd60e51b81526020600482015260066024820152650414444522d360d41b60448201526064016110cb565b600047116118665760405162461bcd60e51b8152602060048201526005602482015264042414c2d360dc1b60448201526064016110cb565b60405147906000906001600160a01b0385169083908381818185875af1925050503d80600081146118b3576040519150601f19603f3d011682016040523d82523d6000602084013e6118b8565b606091505b50509050806117d157600080fd5b6000600080516020614b118339815191526118e081612472565b505060285490565b600080516020614b1183398151915261190081612472565b600082116119415760405162461bcd60e51b815260206004820152600e60248201526d04150532d494e54455256414c2d360941b60448201526064016110cb565b6022829055601c5460215460208054604080516201000090950460ff16151585529184019290925282015260608101839052600080516020614b318339815191529060800161105b565b6000828152600760205260408120611442908361300e565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060600480546111bb90614a81565b6000806000600080516020614b118339815191526119fa81612472565b60215460205460225493509350935050909192565b60003381611a1d8286611f92565b905083811015611a7d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016110cb565b611a8a828686840361247c565b506001949350505050565b60003361127c818585612adb565b600080516020614b11833981519152611abb81612472565b611ac683600161301a565b61146b82600161301a565b600080516020614b11833981519152611ae981612472565b601c805462ff000019166201000084151581029190911791829055602154602080546022546040805160ff96909704959095161515865291850192909252918301526060820152600080516020614b318339815191529060800161105b565b600080516020614b11833981519152611b6081612472565b610fd182613058565b600080516020614b11833981519152611b8181612472565b6023805460ff1916600190811790915560408051918252600060208301819052908201527f20851fa0422d4f14abd10a67c93b0b65e055acfea35fd9d08e4c2489f6ed0d4f9060600160405180910390a150565b600080516020614b11833981519152611bed81612472565b601c80548315156101000261ff00199091161790556040517f53726dfcaf90650aa7eb35524f4d3220f07413c8d6cb404cc8c18bf5591bc1599061105b90841515815260200190565b600080516020614b11833981519152611c4e81612472565b6000611c5c6012600a61493a565b611c669084614a08565b9050611c746012600a61493a565b611c80906103e8614a08565b8111611cbb5760405162461bcd60e51b815260206004820152600a6024820152695448524553482d4c4f5760b01b60448201526064016110cb565b6028555050565b600080516020614b11833981519152611cda81612472565b60235460ff16611d175760405162461bcd60e51b81526020600482015260086024820152674c49512d4e4f4e4560c01b60448201526064016110cb565b611d1f6130d4565b50565b6000818152600760205260408120610e5d90613126565b7f4ebb3eb1732de51e78148107b1735f1eb406c54fc4634032f37c85769c2b55b9611d6381612472565b610fd1600080516020614b1183398151915283611470565b600080516020614b11833981519152611d9381612472565b60018211611dd15760405162461bcd60e51b815260206004820152600b60248201526a5748542d4455522d4c4f5760a81b60448201526064016110cb565b601c805464ff000000001916640100000000179055601e82905542601d55611dfb6012600a61493a565b611e09906301312d00614a08565b6026556023805461ff0019169055604080516001808252602082015260008183015290517f20851fa0422d4f14abd10a67c93b0b65e055acfea35fd9d08e4c2489f6ed0d4f9181900360600190a16040518281527fc7addf6b620f1a592cf9dc47508c92f3cf36054d8b77393f7a90a23ef960acb39060200161105b565b600080516020614b11833981519152611e9f81612472565b600082118015611eaf5750606482105b611eee5760405162461bcd60e51b815260206004820152601060248201526f135056151617d4115490d7d31253525560821b60448201526064016110cb565b611f0f6103e8611f098460115461313090919063ffffffff16565b9061313c565b6026819055601c5460275460408051630100000090930460ff1615158352602083019390935291810191909152600260608201527f9c7f888bfb9f4cac2c303d7608203c132c217df3cf2be1a6025ceae313ef01159060800161105b565b600082815260066020526040902060010154611f8881612472565b61146b8383612cb4565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600080516020614b11833981519152611fd581612472565b601482106120145760405162461bcd60e51b815260206004820152600c60248201526b105414cb55160b531253525560a21b60448201526064016110cb565b6021829055601c5460208054602254604080516201000090950460ff1615158552928401869052918301526060820152600080516020614b318339815191529060800161105b565b600080516020614b1183398151915261207481612472565b6103e88211801561208957506402540be40082105b6120c95760405162461bcd60e51b8152602060048201526011602482015270105414cb5512149154d20b505353d55395607a1b60448201526064016110cb565b6120d56012600a61493a565b6120df9083614a08565b6020818155601c54602154602254604080516201000090940460ff161515845293830191909152918101929092526060820152600080516020614b318339815191529060800161105b565b600080516020614b1183398151915261214281612472565b506001600160a01b03919091166000908152600960205260409020805460ff1916911515919091179055565b600080516020614b1183398151915261218681612472565b50601f805460ff1916911515919091179055565b600080516020614b118339815191526121b281612472565b600182101580156121c757506402540be40082105b6122065760405162461bcd60e51b815260206004820152601060248201526f135056151617d053539517d31253525560821b60448201526064016110cb565b6122126012600a61493a565b611f0f9083614a08565b612224612ea4565b6001600160a01b0381166122895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016110cb565b611d1f81612efe565b600080516020614b118339815191526122aa81612472565b60005b828110156117d1576001600c60008686858181106122db57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906122f091906144ad565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558061232281614abc565b9150506122ad565b600080516020614b1183398151915261234281612472565b603282106123875760405162461bcd60e51b8152602060048201526012602482015271105414cb5512149154d20b54115490d1539560721b60448201526064016110cb565b6120df6103e8611f098460115461313090919063ffffffff16565b6123ac82826119a3565b610fd15760008281526006602090815260408083206001600160a01b03851684529091529020805460ff191660011790556123e43390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000611442836001600160a01b038416613148565b60006001600160e01b03198216637965db0b60e01b1480610e5d57506301ffc9a760e01b6001600160e01b0319831614610e5d565b611d1f8133613197565b6001600160a01b0383166124de5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016110cb565b6001600160a01b03821661253f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016110cb565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b80156125c15760148054601655601580546017556000908190559055611d1f565b60188054601a5560198054601b55600090819055905550565b80156125f157601654601455601754601555611d1f565b601a54601855601b5460195550565b602980546001600160a01b0319166001600160a01b0383169081179091556040805163c45a015560e01b8152905163c45a015591600480820192602092909190829003018186803b15801561265457600080fd5b505afa158015612668573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268c91906144c9565b6001600160a01b031663c9c6539630602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b1580156126e957600080fd5b505afa1580156126fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272191906144c9565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381600087803b15801561276957600080fd5b505af115801561277d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127a191906144c9565b602a80546001600160a01b0319166001600160a01b039290921691821790556127cb906001612c54565b6029546001600160a01b03166000908152600a60205260409020805460ff191660011790556128196128056005546001600160a01b031690565b6029546001600160a01b031660001961247c565b602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b15801561286757600080fd5b505afa15801561287b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289f91906144c9565b60295460405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b390604401602060405180830381600087803b1580156128ed57600080fd5b505af1158015612901573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129259190614641565b50602960009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b15801561297457600080fd5b505afa158015612988573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ac91906144c9565b60405163095ea7b360e01b815230600482015260001960248201526001600160a01b03919091169063095ea7b390604401602060405180830381600087803b1580156129f757600080fd5b505af1158015612a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2f9190614641565b506040516001600160a01b038216907f7e336871192a11cf6144610c966672324a2721225248a567fd1211203248469e90600090a250565b6000612a738484611f92565b905060001981146117d15781811015612ace5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016110cb565b6117d1848484840361247c565b6001600160a01b038316612b1f5760405162461bcd60e51b815260206004820152600b60248201526a046524f4d2d414444522d360ac1b60448201526064016110cb565b6001600160a01b038216612b615760405162461bcd60e51b81526020600482015260096024820152680544f2d414444522d360bc1b60448201526064016110cb565b80612b7757612b7283836000612cd6565b61146b565b6001600160a01b0383166000908152600b602052604090205460ff1680612bb657506001600160a01b0382166000908152600b602052604090205460ff165b15612bc657612b728383836131fb565b601c5460ff16612bf857612bd8613367565b612be38383836133d0565b612bee8383836136ed565b612bf88383613832565b601c546001600160a01b03841660009081526009602052604090205460ff91821615911680612c3f57506001600160a01b03831660009081526009602052604090205460ff165b15612c48575060005b6117d1848484846138d0565b6001600160a01b039091166000908152602b60209081526040808320805494151560ff199586168117909155600a9092529091208054909216179055565b612c9c82826123a2565b600082815260076020526040902061146b9082612428565b612cbe8282613a2f565b600082815260076020526040902061146b9082613a96565b6001600160a01b038316612d3a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016110cb565b6001600160a01b038216612d9c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016110cb565b6001600160a01b03831660009081526020819052604090205481811015612e145760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016110cb565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290612e4b9084906148bc565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612e9791815260200190565b60405180910390a36117d1565b6005546001600160a01b0316331461175f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016110cb565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b603c821115612f8f5760405162461bcd60e51b815260206004820152600b60248201526a4645452d4c494d49542d4d60a81b60448201526064016110cb565b8015612fa45760148054601655829055610fd1565b5060188054601a5555565b603c821115612fee5760405162461bcd60e51b815260206004820152600b60248201526a1191514b53125352550b5360aa1b60448201526064016110cb565b80156130035760158054601755829055610fd1565b5060198054601b5555565b60006114428383613aab565b6001600160a01b039091166000908152600960209081526040808320805494151560ff199586168117909155600a9092529091208054909216179055565b6001600160a01b0381166130975760405162461bcd60e51b81526020600482015260066024820152650414444522d360d41b60448201526064016110cb565b600e546130ae906001600160a01b0316600061301a565b600e80546001600160a01b0319166001600160a01b038316179055611d1f81600161301a565b6023805461ff001916610100179055604080516001808252602082018190528183015290517f20851fa0422d4f14abd10a67c93b0b65e055acfea35fd9d08e4c2489f6ed0d4f916060908290030190a1565b6000610e5d825490565b60006114428284614a08565b600061144282846148d4565b600081815260018301602052604081205461318f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610e5d565b506000610e5d565b6131a182826119a3565b610fd1576131b9816001600160a01b03166014613ae3565b6131c4836020613ae3565b6040516020016131d5929190614747565b60408051601f198184030181529082905262461bcd60e51b82526110cb916004016147f7565b60006103e8600d548361320e9190614a08565b61321891906148d4565b905060006132268284614a27565b9050613233853084612cd6565b61323e858583612cd6565b600080600061324c88613cc5565b156132a45760145460155461326191906148bc565b9250821561329f57601554613277576000613290565b60155483906132869087614a08565b61329091906148d4565b905061329c8186614a27565b91505b6132f2565b6018546019546132b491906148bc565b925082156132f2576019546132ca5760006132e3565b60195483906132d99087614a08565b6132e391906148d4565b90506132ef8186614a27565b91505b821561335d5781600f600082825461330a91906148bc565b92505081905550806010600082825461332391906148bc565b90915550506012805483919060009061333d9084906148bc565b9091555050601380548291906000906133579084906148bc565b90915550505b5050505050505050565b601c54640100000000900460ff161561175f5742601e54603c61338a9190614a08565b601d5461339791906148bc565b101561175f57601c805464ff00000000191690556133b76012600a61493a565b6133c5906301c9c380614a08565b60265561175f6130d4565b601c546301000000900460ff161561146b576133ed838383613ce3565b601c54640100000000900460ff16158061344457506001600160a01b0383166000908152600c602052604090205460ff1615801561344457506001600160a01b0382166000908152600c602052604090205460ff16155b156134ec57602354610100900460ff1661348c5760405162461bcd60e51b81526020600482015260096024820152685443532d545241444560b81b60448201526064016110cb565b601f5460ff16806134a157506134a183613cc5565b806134b057506134b082613cc5565b6134ec5760405162461bcd60e51b815260206004820152600d60248201526c5443532d4143432d534841524560981b60448201526064016110cb565b6134f583613cc5565b156135565760275461350683611732565b61351090836148bc565b11156135515760405162461bcd60e51b815260206004820152601060248201526f1510d4cb5213d31111548b531253525560821b60448201526064016110cb565b6135ba565b61355f82613cc5565b6135ba5760275461356f83611732565b61357990836148bc565b11156135ba5760405162461bcd60e51b815260206004820152601060248201526f1510d4cb5213d31111548b531253525560821b60448201526064016110cb565b6135c382613cc5565b1561361557426135d56002603c614a08565b6001600160a01b0385166000908152602460205260409020546135f891906148bc565b10612b725760405162461bcd60e51b81526004016110cb9061482a565b61361e83613cc5565b1561365357426136306002603c614a08565b6001600160a01b0384166000908152602560205260409020546135f891906148bc565b426136606002603c614a08565b6001600160a01b03851660009081526024602052604090205461368391906148bc565b106136a05760405162461bcd60e51b81526004016110cb9061482a565b426136ad6002603c614a08565b6001600160a01b0384166000908152602560205260409020546136d091906148bc565b1061146b5760405162461bcd60e51b81526004016110cb9061482a565b601c5462010000900460ff161561146b576103e860215461370d60025490565b6137179190614a08565b61372191906148d4565b811061375c5760405162461bcd60e51b815260206004820152600a6024820152694150532d535550504c5960b01b60448201526064016110cb565b61376582613cc5565b1561146b57600061377584611732565b905060205481106137c75761378b6005826148d4565b82106137c75760405162461bcd60e51b815260206004820152600b60248201526a4150532d42414c414e434560a81b60448201526064016110cb565b42602254603c6137d79190614a08565b6001600160a01b0386166000908152602460205260409020546137fa91906148bc565b106117d15760405162461bcd60e51b81526020600482015260086024820152674150532d54494d4560c01b60448201526064016110cb565b601c5460ff1615801561384b575061384982613cc5565b155b801561385e5750601c54610100900460ff165b801561388357506001600160a01b03821660009081526009602052604090205460ff16155b80156138a857506001600160a01b03811660009081526009602052604090205460ff16155b15610fd157601c805460ff191660011790556138c2613e4b565b601c805460ff191690555050565b60006138db85613cc5565b9050600082156139995760006138f18584614033565b90508060600151816040015161390791906148bc565b91508115613997578060400151600f600082825461392591906148bc565b90915550506060810151601080546000906139419084906148bc565b909155505060408101516012805460009061395d9084906148bc565b90915550506060810151601380546000906139799084906148bc565b9091555061398a9050873084612cd6565b6139948286614a27565b94505b505b81156139bf576001600160a01b0385166000908152602560205260409020429055613a1c565b6139c885613cc5565b156139ed576001600160a01b0386166000908152602460205260409020429055613a1c565b6001600160a01b0380861660009081526025602090815260408083204290819055938a16835260249091529020555b613a27868686612cd6565b505050505050565b613a3982826119a3565b15610fd15760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000611442836001600160a01b0384166140a7565b6000826000018281548110613ad057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60606000613af2836002614a08565b613afd9060026148bc565b67ffffffffffffffff811115613b2357634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613b4d576020820181803683370190505b509050600360fc1b81600081518110613b7657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613bb357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000613bd7846002614a08565b613be29060016148bc565b90505b6001811115613c76576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613c2457634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110613c4857634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93613c6f81614a6a565b9050613be5565b5083156114425760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016110cb565b6001600160a01b03166000908152602b602052604090205460ff1690565b613cec83613cc5565b15613d555760265481111580613d1a57506001600160a01b0382166000908152600a602052604090205460ff165b612b725760405162461bcd60e51b815260206004820152600c60248201526b54582d4c494d49542d42555960a01b60448201526064016110cb565b613d5e82613cc5565b15613dc85760265481111580613d8c57506001600160a01b0383166000908152600a602052604090205460ff165b612b725760405162461bcd60e51b815260206004820152600d60248201526c15160b53125352550b54d15313609a1b60448201526064016110cb565b60265481111580613e1457506001600160a01b0383166000908152600a602052604090205460ff168015613e1457506001600160a01b0382166000908152600a602052604090205460ff165b61146b5760405162461bcd60e51b815260206004820152600860248201526715160b531253525560c21b60448201526064016110cb565b6000613e5630611732565b90506000600f54601054613e6a91906148bc565b9050811580613e77575080155b80613e83575060285481105b15613e8f57505061175f565b600060028260105485613ea29190614a08565b613eac91906148d4565b613eb691906148d4565b90506000613ec484836141c4565b905047613ed182306141d0565b6000613edd47836141c4565b90506000613efa86611f09600f548561313090919063ffffffff16565b90506000613f088284614a27565b90506000601054118015613f1c5750600081115b15613f8257613f2b8682614356565b7f17bbfb9a6069321b6ded73bd96327c9e6b7212a5cd51ff219cd61370acafb5618682613f63896010546141c490919063ffffffff16565b6040805193845260208401929092529082015260600160405180910390a15b600e546040516000916001600160a01b03169084908381818185875af1925050503d8060008114613fcf576040519150601f19603f3d011682016040523d82523d6000602084013e613fd4565b606091505b5050600f546040805191825260208201869052821515908201529091507fe4b0471ec14ebebbb513d957de87fec57e9abdbdf15f1afedcce783601dd89189060600160405180910390a1505060006010819055600f5550505050505050565b61405e6040518060800160405280600081526020016000815260200160008152602001600081525090565b82815261406b8383614406565b604082015261407a838361445d565b60608201819052604082015161409c91906140969086906141c4565b906141c4565b602082015292915050565b600081815260018301602052604081205480156141ba5760006140cb600183614a27565b85549091506000906140df90600190614a27565b905081811461416057600086600001828154811061410d57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061413e57634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061417f57634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610e5d565b6000915050610e5d565b60006114428284614a27565b604080516002808252606082018352600092602083019080368337019050509050308160008151811061421357634e487b7160e01b600052603260045260246000fd5b6001600160a01b03928316602091820292909201810191909152602954604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561426757600080fd5b505afa15801561427b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061429f91906144c9565b816001815181106142c057634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526029546142e6913091168561247c565b60295460405163791ac94760e01b81526001600160a01b039091169063791ac9479061431f90869060009086908890429060040161484c565b600060405180830381600087803b15801561433957600080fd5b505af115801561434d573d6000803e3d6000fd5b50505050505050565b60295461436e9030906001600160a01b03168461247c565b60295460405163f305d71960e01b81526001600160a01b039091169063f305d7199083906143ad9030908790600090819061dead9042906004016147bc565b6060604051808303818588803b1580156143c657600080fd5b505af11580156143da573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906143ff919061471a565b5050505050565b600081156144395760145461441c576000614432565b601454614432906103e890611f09908690613130565b9050610e5d565b601854614447576000614432565b601854614432906103e890611f09908690613130565b6000811561448957601554614473576000614432565b601554614432906103e890611f09908690613130565b601954614497576000614432565b601954614432906103e890611f09908690613130565b6000602082840312156144be578081fd5b813561144281614aed565b6000602082840312156144da578081fd5b815161144281614aed565b600080604083850312156144f7578081fd5b823561450281614aed565b9150602083013561451281614aed565b809150509250929050565b600080600060608486031215614531578081fd5b833561453c81614aed565b9250602084013561454c81614aed565b929592945050506040919091013590565b6000806040838503121561456f578182fd5b823561457a81614aed565b9150602083013561451281614b02565b6000806040838503121561459c578182fd5b82356145a781614aed565b946020939093013593505050565b600080602083850312156145c7578182fd5b823567ffffffffffffffff808211156145de578384fd5b818501915085601f8301126145f1578384fd5b8135818111156145ff578485fd5b8660208260051b8501011115614613578485fd5b60209290920196919550909350505050565b600060208284031215614636578081fd5b813561144281614b02565b600060208284031215614652578081fd5b815161144281614b02565b60006020828403121561466e578081fd5b5035919050565b60008060408385031215614687578182fd5b82359150602083013561451281614aed565b600080604083850312156146ab578182fd5b50508035926020909101359150565b6000602082840312156146cb578081fd5b81356001600160e01b031981168114611442578182fd5b6000806000606084860312156146f6578081fd5b8335925060208401359150604084013561470f81614b02565b809150509250925092565b60008060006060848603121561472e578081fd5b8351925060208401519150604084015190509250925092565b60007f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008252835161477f816017850160208801614a3e565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516147b0816028840160208801614a3e565b01602801949350505050565b6001600160a01b039687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b6000602082528251806020840152614816816040850160208701614a3e565b601f01601f19169190910160400192915050565b6020808252600890820152675443532d54494d4560c01b604082015260600190565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b8181101561489b5784516001600160a01b031683529383019391830191600101614876565b50506001600160a01b03969096166060850152505050608001529392505050565b600082198211156148cf576148cf614ad7565b500190565b6000826148ef57634e487b7160e01b81526012600452602481fd5b500490565b80825b60018086116149065750614931565b81870482111561491857614918614ad7565b8086161561492557918102915b9490941c9380026148f7565b94509492505050565b6000611442600019848460008261495357506001611442565b8161496057506000611442565b81600181146149765760028114614980576149ad565b6001915050611442565b60ff84111561499157614991614ad7565b6001841b9150848211156149a7576149a7614ad7565b50611442565b5060208310610133831016604e8410600b84101617156149e0575081810a838111156149db576149db614ad7565b611442565b6149ed84848460016148f4565b8086048211156149ff576149ff614ad7565b02949350505050565b6000816000190483118215151615614a2257614a22614ad7565b500290565b600082821015614a3957614a39614ad7565b500390565b60005b83811015614a59578181015183820152602001614a41565b838111156117d15750506000910152565b600081614a7957614a79614ad7565b506000190190565b600181811c90821680614a9557607f821691505b60208210811415614ab657634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614ad057614ad0614ad7565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114611d1f57600080fd5b8015158114611d1f57600080fdfee33cade2d66e04fd0493fc676b10225974e8a5e7a703b4ffe78a5b4509bff0b98ee018fc6d9be726281c70ad01c6b66e2029e32016d05bc754dbf909b362bb55a2646970667358221220de5a14271d51ac94baafa93df62bdd5e0add6149d816bd4a508ff9aaed5c740764736f6c63430008030033

Deployed Bytecode Sourcemap

97667:37059:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95495:214;;;;;;;;;;-1:-1:-1;95495:214:0;;;;;:::i;:::-;;:::i;:::-;;;8180:14:1;;8173:22;8155:41;;8143:2;8128:18;95495:214:0;;;;;;;;114234:685;;;;;;;;;;;;;:::i;:::-;;107601:206;;;;;;;;;;-1:-1:-1;107601:206:0;;;;;:::i;:::-;;:::i;106697:495::-;;;;;;;;;;-1:-1:-1;106697:495:0;;;;;:::i;:::-;;:::i;73171:100::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;107969:170::-;;;;;;;;;;;;;:::i;:::-;;;;26691:25:1;;;26747:2;26732:18;;26725:34;;;;26775:18;;;26768:34;26679:2;26664:18;107969:170:0;26646:162:1;75522:201:0;;;;;;;;;;-1:-1:-1;75522:201:0;;;;;:::i;:::-;;:::i;116377:126::-;;;;;;;;;;-1:-1:-1;116377:126:0;;;;;:::i;:::-;;:::i;116776:375::-;;;;;;;;;;-1:-1:-1;116776:375:0;;;;;:::i;:::-;;:::i;115993:180::-;;;;;;;;;;-1:-1:-1;115993:180:0;;;;;:::i;:::-;;:::i;100497:32::-;;;;;;;;;;;;;;;;;;;9113:25:1;;;9101:2;9086:18;100497:32:0;9068:76:1;74291:108:0;;;;;;;;;;-1:-1:-1;74379:12:0;;74291:108;;117163:182;;;;;;;;;;-1:-1:-1;117163:182:0;;;;;:::i;:::-;;:::i;113576:132::-;;;;;;;;;;-1:-1:-1;113576:132:0;;;;;:::i;:::-;;:::i;105405:151::-;;;;;;;;;;-1:-1:-1;105489:15:0;:28;105519;;105405:151;;;;26076:25:1;;;26132:2;26117:18;;26110:34;;;;26049:18;105405:151:0;26031:119:1;76303:295:0;;;;;;;;;;-1:-1:-1;76303:295:0;;;;;:::i;:::-;;:::i;91070:131::-;;;;;;;;;;-1:-1:-1;91070:131:0;;;;;:::i;:::-;91144:7;91171:12;;;:6;:12;;;;;:22;;;;91070:131;118497:130;;;;;;;;;;-1:-1:-1;118497:130:0;;;;;:::i;:::-;;:::i;91511:147::-;;;;;;;;;;-1:-1:-1;91511:147:0;;;;;:::i;:::-;;:::i;74133:93::-;;;;;;;;;;-1:-1:-1;74133:93:0;;74216:2;26955:36:1;;26943:2;26928:18;74133:93:0;26910:87:1;92655:218:0;;;;;;;;;;-1:-1:-1;92655:218:0;;;;;:::i;:::-;;:::i;77007:238::-;;;;;;;;;;-1:-1:-1;77007:238:0;;;;;:::i;:::-;;:::i;115859:122::-;;;;;;;;;;-1:-1:-1;115859:122:0;;;;;:::i;:::-;-1:-1:-1;;;;;115954:19:0;115930:4;115954:19;;;:10;:19;;;;;;;;;115859:122;106389:152;;;;;;;;;;-1:-1:-1;106389:152:0;;;;;:::i;:::-;;:::i;115427:292::-;;;;;;;;;;;;;:::i;101669:30::-;;;;;;;;;;-1:-1:-1;101669:30:0;;;;;;;;;;;106243:134;;;;;;;;;;-1:-1:-1;106243:134:0;;;;;:::i;:::-;-1:-1:-1;;;;;106342:27:0;106318:4;106342:27;;;:18;:27;;;;;;;;;106243:134;116185:186;;;;;;;;;;-1:-1:-1;116185:186:0;;;;;:::i;:::-;;:::i;101577:30::-;;;;;;;;;;-1:-1:-1;101577:30:0;;;;;;;;;;;106553:136;;;;;;;;;;-1:-1:-1;106553:136:0;;;;;:::i;:::-;-1:-1:-1;;;;;106652:29:0;106628:4;106652:29;;;:20;:29;;;;;;;;;106553:136;113790:170;;;;;;;;;;-1:-1:-1;113790:170:0;;;;;:::i;:::-;;:::i;105751:267::-;;;;;;;;;;-1:-1:-1;105751:267:0;;;;;:::i;:::-;;:::i;74462:127::-;;;;;;;;;;-1:-1:-1;74462:127:0;;;;;:::i;:::-;;:::i;85840:103::-;;;;;;;;;;;;;:::i;99360:66::-;;;;;;;;;;;;99400:26;99360:66;;110453:428;;;;;;;;;;-1:-1:-1;110453:428:0;;;;;:::i;:::-;;:::i;114982:437::-;;;;;;;;;;-1:-1:-1;114982:437:0;;;;;:::i;:::-;;:::i;112323:111::-;;;;;;;;;;;;;:::i;109487:259::-;;;;;;;;;;-1:-1:-1;109487:259:0;;;;;:::i;:::-;;:::i;85192:87::-;;;;;;;;;;-1:-1:-1;85265:6:0;;-1:-1:-1;;;;;85265:6:0;85192:87;;;-1:-1:-1;;;;;6771:32:1;;;6753:51;;6741:2;6726:18;85192:87:0;6708:102:1;96308:153:0;;;;;;;;;;-1:-1:-1;96308:153:0;;;;;:::i;:::-;;:::i;89530:147::-;;;;;;;;;;-1:-1:-1;89530:147:0;;;;;:::i;:::-;;:::i;73390:104::-;;;;;;;;;;;;;:::i;109892:156::-;;;;;;;;;;;;;:::i;88635:49::-;;;;;;;;;;-1:-1:-1;88635:49:0;88680:4;88635:49;;77748:436;;;;;;;;;;-1:-1:-1;77748:436:0;;;;;:::i;:::-;;:::i;100393:32::-;;;;;;;;;;;;;;;;104263:41;;;;;;;;;;-1:-1:-1;104263:41:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;74795:193;;;;;;;;;;-1:-1:-1;74795:193:0;;;;;:::i;:::-;;:::i;107304:217::-;;;;;;;;;;-1:-1:-1;107304:217:0;;;;;:::i;:::-;;:::i;108214:192::-;;;;;;;;;;-1:-1:-1;108214:192:0;;;;;:::i;:::-;;:::i;110302:139::-;;;;;;;;;;-1:-1:-1;110302:139:0;;;;;:::i;:::-;;:::i;114075:153::-;;;;;;;;;;;;;:::i;111740:193::-;;;;;;;;;;-1:-1:-1;111740:193:0;;;;;:::i;:::-;;:::i;112026:240::-;;;;;;;;;;-1:-1:-1;112026:240:0;;;;;:::i;:::-;;:::i;112599:142::-;;;;;;;;;;;;;:::i;96635:::-;;;;;;;;;;-1:-1:-1;96635:142:0;;;;;:::i;:::-;;:::i;105131:130::-;;;;;;;;;;-1:-1:-1;105131:130:0;;;;;:::i;:::-;;:::i;112876:603::-;;;;;;;;;;-1:-1:-1;112876:603:0;;;;;:::i;:::-;;:::i;100282:37::-;;;;;;;;;;-1:-1:-1;100282:37:0;;;;-1:-1:-1;;;;;100282:37:0;;;110955:345;;;;;;;;;;-1:-1:-1;110955:345:0;;;;;:::i;:::-;;:::i;91951:149::-;;;;;;;;;;-1:-1:-1;91951:149:0;;;;;:::i;:::-;;:::i;102768:34::-;;;;;;;;;;-1:-1:-1;102768:34:0;;;;;;;;75051:151;;;;;;;;;;-1:-1:-1;75051:151:0;;;;;:::i;:::-;;:::i;109174:251::-;;;;;;;;;;-1:-1:-1;109174:251:0;;;;;:::i;:::-;;:::i;108785:314::-;;;;;;;;;;-1:-1:-1;108785:314:0;;;;;:::i;:::-;;:::i;106030:148::-;;;;;;;;;;-1:-1:-1;106030:148:0;;;;;:::i;:::-;;:::i;110136:120::-;;;;;;;;;;-1:-1:-1;110136:120:0;;;;;:::i;:::-;;:::i;111357:341::-;;;;;;;;;;-1:-1:-1;111357:341:0;;;;;:::i;:::-;;:::i;103089:33::-;;;;;;;;;;-1:-1:-1;103089:33:0;;;;;;;;;;;99433:64;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;99433:64:0;;86098:201;;;;;;;;;;-1:-1:-1;86098:201:0;;;;;:::i;:::-;;:::i;116511:188::-;;;;;;;;;;-1:-1:-1;116511:188:0;;;;;:::i;:::-;;:::i;115731:122::-;;;;;;;;;;-1:-1:-1;115731:122:0;;;;;:::i;:::-;-1:-1:-1;;;;;115826:19:0;115802:4;115826:19;;;:10;:19;;;;;;;;;115731:122;102849:31;;;;;;;;;;-1:-1:-1;102849:31:0;;;;;;;;;;;108479:298;;;;;;;;;;-1:-1:-1;108479:298:0;;;;;:::i;:::-;;:::i;95495:214::-;95580:4;-1:-1:-1;;;;;;95604:57:0;;-1:-1:-1;;;95604:57:0;;:97;;;95665:36;95689:11;95665:23;:36::i;:::-;95597:104;95495:214;-1:-1:-1;;95495:214:0:o;114234:685::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;114399:13:::1;::::0;114415:12:::1;::::0;114367:61:::1;::::0;114384:4:::1;::::0;-1:-1:-1;;;;;114399:13:0;;::::1;::::0;114367:8:::1;:61::i;:::-;114633:13;::::0;-1:-1:-1;;;;;114633:13:0::1;:29;114670:21;114715:4;114721:24;114715:4:::0;114721:9:::1;:24::i;:::-;114746:1;114748::::0;114750:7:::1;85265:6:::0;;-1:-1:-1;;;;;85265:6:0;85192:87;;114750:7:::1;114758:15;114633:141;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;114799:22;:20;:22::i;:::-;114849:11;::::0;114878:13:::1;::::0;114842:69:::1;::::0;-1:-1:-1;;;114842:69:0;;-1:-1:-1;;;;;114878:13:0;;::::1;114842:69;::::0;::::1;7298:51:1::0;-1:-1:-1;;7365:18:1;;;7358:34;114849:11:0;::::1;::::0;114842:27:::1;::::0;7271:18:1;;114842:69:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;114234:685:::0;:::o;107601:206::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;107683:10:::1;:20:::0;;-1:-1:-1;;107683:20:0::1;::::0;;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;;107749:12:::1;::::0;107763:16:::1;::::0;107721:78:::1;::::0;;107683:20:::1;107737:10:::0;;;::::1;::::0;;;::::1;8811:14:1::0;8804:22;8786:41;;8858:2;8843:18;;8836:34;;;;8886:18;;;8879:34;99243:1:0::1;8944:2:1::0;8929:18;;8922:34;107721:78:0::1;::::0;8773:3:1;8758:19;107721:78:0::1;;;;;;;;107601:206:::0;;:::o;106697:495::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;106804:1:::1;106796:5;:9;:35;;;;;98585:12;106809:5;:22;106796:35;106788:61;;;::::0;-1:-1:-1;;;106788:61:0;;11176:2:1;106788:61:0::1;::::0;::::1;11158:21:1::0;11215:2;11195:18;;;11188:30;-1:-1:-1;;;11234:18:1;;;11227:43;11287:18;;106788:61:0::1;;;;;;;;;106862:17;106890:23;98476:2;106890;:23;:::i;:::-;106882:31;::::0;:5;:31:::1;:::i;:::-;106862:51;;98956:4;106995:12;;107010:1;106995:16;;;;:::i;:::-;106994:34;;;;:::i;:::-;106981:9;:48;106973:74;;;::::0;-1:-1:-1;;;106973:74:0;;15106:2:1;106973:74:0::1;::::0;::::1;15088:21:1::0;15145:2;15125:18;;;15118:30;-1:-1:-1;;;15164:18:1;;;15157:43;15217:18;;106973:74:0::1;15078:163:1::0;106973:74:0::1;107060:16;:28:::0;;;107122:10:::1;::::0;107134:12:::1;::::0;107106:78:::1;::::0;;107122:10;;;::::1;;;8811:14:1::0;8804:22;8786:41;;8858:2;8843:18;;8836:34;;;;8886:18;;8879:34;;;99243:1:0::1;8944:2:1::0;8929:18;;8922:34;107106:78:0::1;::::0;8773:3:1;8758:19;107106:78:0::1;;;;;;;89153:1;106697:495:::0;;:::o;73171:100::-;73225:13;73258:5;73251:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73171:100;:::o;107969:170::-;108035:7;108044;108053;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;;108081:12:0::1;::::0;108095:16:::1;::::0;108081:12;;108095:16;;-1:-1:-1;99243:1:0::1;::::0;-1:-1:-1;107969:170:0:o;75522:201::-;75605:4;70891:10;75661:32;70891:10;75677:7;75686:6;75661:8;:32::i;:::-;-1:-1:-1;75711:4:0;;75522:201;-1:-1:-1;;;75522:201:0:o;116377:126::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;116470:13:0::1;:28:::0;116377:126::o;116776:375::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;116857:5:::1;116854:290;;;116918:19;116932:4;116918:13;:19::i;:::-;116973:20;116987:5;116973:13;:20::i;:::-;116854:290;;;117060:20;117075:4;117060:14;:20::i;:::-;117117:21;117132:5;117117:14;:21::i;115993:180::-:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;116097:3:::1;116096:4;:28;;;-1:-1:-1::0;;;;;;116105:19:0;::::1;;::::0;;;:10:::1;:19;::::0;;;;;::::1;;116104:20;116096:28;116088:47;;;::::0;-1:-1:-1;;;116088:47:0;;11852:2:1;116088:47:0::1;::::0;::::1;11834:21:1::0;11891:1;11871:18;;;11864:29;-1:-1:-1;;;11909:18:1;;;11902:36;11955:18;;116088:47:0::1;11824:155:1::0;116088:47:0::1;-1:-1:-1::0;;;;;;116140:19:0;;;::::1;;::::0;;;:10:::1;:19;::::0;;;;:25;;-1:-1:-1;;116140:25:0::1;::::0;::::1;;::::0;;;::::1;::::0;;115993:180::o;117163:182::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;;;;;117271:24:0;::::1;117263:41;;;;-1:-1:-1::0;;;117263:41:0::1;;;;;;13690:2:1::0;13672:21;;;13729:1;13709:18;;;13702:29;-1:-1:-1;;;13762:2:1;13747:18;;13740:34;13806:2;13791:18;;13662:153;117263:41:0::1;117315:22;117326:10;117315;:22::i;113576:132::-:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;113670:20:0::1;:30:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;113670:30:0;;::::1;::::0;;;::::1;::::0;;113576:132::o;76303:295::-;76434:4;70891:10;76492:38;76508:4;70891:10;76523:6;76492:15;:38::i;:::-;76541:27;76551:4;76557:2;76561:6;76541:9;:27::i;:::-;76586:4;76579:11;;;76303:295;;;;;;:::o;118497:130::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;118595:24:::1;118607:4;118613:5;118595:11;:24::i;:::-;118497:130:::0;;;:::o;91511:147::-;91144:7;91171:12;;;:6;:12;;;;;:22;;;89126:16;89137:4;89126:10;:16::i;:::-;91625:25:::1;91636:4;91642:7;91625:10;:25::i;92655:218::-:0;-1:-1:-1;;;;;92751:23:0;;70891:10;92751:23;92743:83;;;;-1:-1:-1;;;92743:83:0;;24518:2:1;92743:83:0;;;24500:21:1;24557:2;24537:18;;;24530:30;24596:34;24576:18;;;24569:62;-1:-1:-1;;;24647:18:1;;;24640:45;24702:19;;92743:83:0;24490:237:1;92743:83:0;92839:26;92851:4;92857:7;92839:11;:26::i;77007:238::-;77095:4;70891:10;77151:64;70891:10;77167:7;77204:10;77176:25;70891:10;77167:7;77176:9;:25::i;:::-;:38;;;;:::i;:::-;77151:8;:64::i;106389:152::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;;;;;;106494:29:0;;;::::1;;::::0;;;:20:::1;:29;::::0;;;;:39;;-1:-1:-1;;106494:39:0::1;::::0;::::1;;::::0;;;::::1;::::0;;106389:152::o;115427:292::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;115512:22:::1;::::0;::::1;::::0;::::1;;;115511:23;115503:49;;;::::0;-1:-1:-1;;;115503:49:0;;23086:2:1;115503:49:0::1;::::0;::::1;23068:21:1::0;23125:2;23105:18;;;23098:30;-1:-1:-1;;;23144:18:1;;;23137:43;23197:18;;115503:49:0::1;23058:163:1::0;115503:49:0::1;115596:22;::::0;115565:80:::1;::::0;115589:4:::1;::::0;-1:-1:-1;;;;;115596:22:0::1;115620:24;115589:4:::0;115620:9:::1;:24::i;:::-;115565:15;:80::i;:::-;-1:-1:-1::0;115678:1:0::1;115658:17;:21:::0;;;115690:17:::1;:21:::0;115427:292::o;116185:186::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;116289:3:::1;116288:4;:28;;;-1:-1:-1::0;;;;;;116297:19:0;::::1;;::::0;;;:10:::1;:19;::::0;;;;;::::1;;116296:20;116288:28;116280:47;;;::::0;-1:-1:-1;;;116280:47:0;;11518:2:1;116280:47:0::1;::::0;::::1;11500:21:1::0;11557:1;11537:18;;;11530:29;-1:-1:-1;;;11575:18:1;;;11568:36;11621:18;;116280:47:0::1;11490:155:1::0;116280:47:0::1;-1:-1:-1::0;;;;;;116338:19:0;;;::::1;;::::0;;;:10:::1;:19;::::0;;;;:25;;-1:-1:-1;;116338:25:0::1;::::0;::::1;;::::0;;;::::1;::::0;;116185:186::o;113790:170::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;113882:13:::1;:22:::0;;-1:-1:-1;;113882:22:0::1;::::0;;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;;113920:32:::1;::::0;113882:22:::1;113938:13:::0;;;::::1;;8180:14:1::0;8173:22;8155:41;;113920:32:0::1;::::0;8143:2:1;8128:18;113920:32:0::1;8110:92:1::0;105751:267:0;105805:7;105814;105837:5;105834:177;;;-1:-1:-1;;105866:8:0;:21;105889;;105858:53;;105834:177;-1:-1:-1;;105952:9:0;:22;105976;;105834:177;105751:267;;;:::o;74462:127::-;-1:-1:-1;;;;;74563:18:0;74536:7;74563:18;;;;;;;;;;;;74462:127::o;85840:103::-;85078:13;:11;:13::i;:::-;85905:30:::1;85932:1;85905:18;:30::i;:::-;85840:103::o:0;110453:428::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;99141:3:::1;110695:27;110710:12:::0;110695;:27:::1;:::i;:::-;:47;;110687:67;;;::::0;-1:-1:-1;;;110687:67:0;;20636:2:1;110687:67:0::1;::::0;::::1;20618:21:1::0;20675:1;20655:18;;;20648:29;-1:-1:-1;;;20693:18:1;;;20686:37;20740:18;;110687:67:0::1;20608:156:1::0;110687:67:0::1;110774:44;110798:12;110812:5;110774:23;:44::i;:::-;110829;110853:12;110867:5;110829:23;:44::i;:::-;110453:428:::0;;;;:::o;114982:437::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;;;;;115093:23:0;::::1;115085:42;;;::::0;-1:-1:-1;;;115085:42:0;;16808:2:1;115085:42:0::1;::::0;::::1;16790:21:1::0;16847:1;16827:18;;;16820:29;-1:-1:-1;;;16865:18:1;;;16858:36;16911:18;;115085:42:0::1;16780:155:1::0;115085:42:0::1;115170:1;115146:21;:25;115138:43;;;::::0;-1:-1:-1;;;115138:43:0;;18873:2:1;115138:43:0::1;::::0;::::1;18855:21:1::0;18912:1;18892:18;;;18885:29;-1:-1:-1;;;18930:18:1;;;18923:35;18975:18;;115138:43:0::1;18845:154:1::0;115138:43:0::1;115307:42;::::0;115212:21:::1;::::0;115195:14:::1;::::0;-1:-1:-1;;;;;115307:23:0;::::1;::::0;115212:21;;115195:14;115307:42;115195:14;115307:42;115212:21;115307:23;:42:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115289:60;;;115370:7;115366:46;;115392:8;::::0;::::1;112323:111:::0;112388:7;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;;112415:11:0::1;::::0;;112323:111::o;109487:259::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;109600:1:::1;109589:8;:12;109581:39;;;::::0;-1:-1:-1;;;109581:39:0;;20971:2:1;109581:39:0::1;::::0;::::1;20953:21:1::0;21010:2;20990:18;;;20983:30;-1:-1:-1;;;21029:18:1;;;21022:44;21083:18;;109581:39:0::1;20943:164:1::0;109581:39:0::1;109633:12;:23:::0;;;109690:10:::1;::::0;109702:9:::1;::::0;109713:10:::1;::::0;;109674:64:::1;::::0;;109690:10;;;::::1;;;8811:14:1::0;8804:22;8786:41;;8843:18;;;8836:34;;;;8886:18;;8879:34;8944:2;8929:18;;8922:34;;;-1:-1:-1;;;;;;;;;;;109674:64:0;8773:3:1;8758:19;109674:64:0::1;8740:222:1::0;96308:153:0;96398:7;96425:18;;;:12;:18;;;;;:28;;96447:5;96425:21;:28::i;89530:147::-;89616:4;89640:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;89640:29:0;;;;;;;;;;;;;;;89530:147::o;73390:104::-;73446:13;73479:7;73472:14;;;;;:::i;109892:156::-;109958:7;109967;109976;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;110004:9:::1;;110015:10;;110027:12;;109996:44;;;;;;109892:156:::0;;;;:::o;77748:436::-;77841:4;70891:10;77841:4;77924:25;70891:10;77941:7;77924:9;:25::i;:::-;77897:52;;77988:15;77968:16;:35;;77960:85;;;;-1:-1:-1;;;77960:85:0;;24112:2:1;77960:85:0;;;24094:21:1;24151:2;24131:18;;;24124:30;24190:34;24170:18;;;24163:62;-1:-1:-1;;;24241:18:1;;;24234:35;24286:19;;77960:85:0;24084:227:1;77960:85:0;78081:60;78090:5;78097:7;78125:15;78106:16;:34;78081:8;:60::i;:::-;-1:-1:-1;78172:4:0;;77748:436;-1:-1:-1;;;;77748:436:0:o;74795:193::-;74874:4;70891:10;74930:28;70891:10;74947:2;74951:6;74930:9;:28::i;107304:217::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;107431:35:::1;107447:12;107461:4;107431:15;:35::i;:::-;107477:36;107493:13;107508:4;107477:15;:36::i;108214:192::-:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;108296:10:::1;:20:::0;;-1:-1:-1;;108296:20:0::1;::::0;;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;;108362:9:::1;::::0;108373:10:::1;::::0;;108385:12:::1;::::0;108334:64:::1;::::0;;108296:20:::1;108350:10:::0;;;::::1;::::0;;;::::1;8811:14:1::0;8804:22;8786:41;;8843:18;;;8836:34;;;;8886:18;;;8879:34;8944:2;8929:18;;8922:34;-1:-1:-1;;;;;;;;;;;108334:64:0;8773:3:1;8758:19;108334:64:0::1;8740:222:1::0;110302:139:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;110402:31:::1;110425:7;110402:22;:31::i;114075:153::-:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;114148:14:::1;:21:::0;;-1:-1:-1;;114148:21:0::1;114165:4;114148:21:::0;;::::1;::::0;;;114187:33:::1;::::0;;8391:41:1;;;-1:-1:-1;8463:2:1;8448:18;;8441:50;;;8507:18;;;8500:50;114187:33:0::1;::::0;8379:2:1;8364:18;114187:33:0::1;;;;;;;114075:153:::0;:::o;111740:193::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;111840:22:::1;:32:::0;;;::::1;;;;-1:-1:-1::0;;111840:32:0;;::::1;;::::0;;111888:37:::1;::::0;::::1;::::0;::::1;::::0;111865:7;8180:14:1;8173:22;8155:41;;8143:2;8128:18;;8110:92;112026:240:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;112119:17:::1;112148:23;98476:2;112148;:23;:::i;:::-;112139:32;::::0;:6;:32:::1;:::i;:::-;112119:52:::0;-1:-1:-1;98802:23:0::1;98476:2;98802;:23;:::i;:::-;98788:37;::::0;:11:::1;:37;:::i;:::-;112186:9;:30;112178:53;;;::::0;-1:-1:-1;;;112178:53:0;;23428:2:1;112178:53:0::1;::::0;::::1;23410:21:1::0;23467:2;23447:18;;;23440:30;-1:-1:-1;;;23486:18:1;;;23479:40;23536:18;;112178:53:0::1;23400:160:1::0;112178:53:0::1;112238:11;:23:::0;-1:-1:-1;;112026:240:0:o;112599:142::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;112682:14:::1;::::0;::::1;;112674:35;;;::::0;-1:-1:-1;;;112674:35:0;;12996:2:1;112674:35:0::1;::::0;::::1;12978:21:1::0;13035:1;13015:18;;;13008:29;-1:-1:-1;;;13053:18:1;;;13046:38;13101:18;;112674:35:0::1;12968:157:1::0;112674:35:0::1;112719:14;:12;:14::i;:::-;112599:142:::0;:::o;96635:::-;96715:7;96742:18;;;:12;:18;;;;;:27;;:25;:27::i;105131:130::-;99400:26;89126:16;89137:4;89126:10;:16::i;:::-;105221:32:::1;-1:-1:-1::0;;;;;;;;;;;105245:7:0::1;105221:9;:32::i;112876:603::-:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;112996:1:::1;112985:8;:12;112977:36;;;::::0;-1:-1:-1;;;112977:36:0;;22407:2:1;112977:36:0::1;::::0;::::1;22389:21:1::0;22446:2;22426:18;;;22419:30;-1:-1:-1;;;22465:18:1;;;22458:41;22516:18;;112977:36:0::1;22379:161:1::0;112977:36:0::1;113024:13;:20:::0;;-1:-1:-1;;113024:20:0::1;::::0;::::1;::::0;;113055:11:::1;:22:::0;;;113099:15:::1;113088:8;:26:::0;113200:23:::1;98476:2;113200;:23;:::i;:::-;113185:38;::::0;:12:::1;:38;:::i;:::-;113170:12;:53:::0;113276:11:::1;:19:::0;;-1:-1:-1;;113276:19:0::1;::::0;;113344:32:::1;::::0;;-1:-1:-1;8391:41:1;;;8463:2;8448:18;;8441:50;-1:-1:-1;8507:18:1;;;8500:50;113344:32:0;;::::1;::::0;;;;8379:2:1;113344:32:0;;::::1;113438:33;::::0;9113:25:1;;;113438:33:0::1;::::0;9101:2:1;9086:18;113438:33:0::1;9068:76:1::0;110955:345:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;111077:1:::1;111062:12;:16;:38;;;;;111097:3;111082:12;:18;111062:38;111054:67;;;::::0;-1:-1:-1;;;111054:67:0;;18528:2:1;111054:67:0::1;::::0;::::1;18510:21:1::0;18567:2;18547:18;;;18540:30;-1:-1:-1;;;18586:18:1;;;18579:46;18642:18;;111054:67:0::1;18500:166:1::0;111054:67:0::1;111147:49;98956:4;111147:30;111164:12;111147;;:16;;:30;;;;:::i;:::-;:34:::0;::::1;:49::i;:::-;111132:12;:64:::0;;;111230:10:::1;::::0;111256:16:::1;::::0;111214:78:::1;::::0;;111230:10;;;::::1;;;8811:14:1::0;8804:22;8786:41;;8858:2;8843:18;;8836:34;;;;8886:18;;;8879:34;;;;99243:1:0::1;8944:2:1::0;8929:18;;8922:34;111214:78:0::1;::::0;8773:3:1;8758:19;111214:78:0::1;8740:222:1::0;91951:149:0;91144:7;91171:12;;;:6;:12;;;;;:22;;;89126:16;89137:4;89126:10;:16::i;:::-;92066:26:::1;92078:4;92084:7;92066:11;:26::i;75051:151::-:0;-1:-1:-1;;;;;75167:18:0;;;75140:7;75167:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;75051:151::o;109174:251::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;109284:2:::1;109274:7;:12;109266:37;;;::::0;-1:-1:-1;;;109266:37:0;;14765:2:1;109266:37:0::1;::::0;::::1;14747:21:1::0;14804:2;14784:18;;;14777:30;-1:-1:-1;;;14823:18:1;;;14816:42;14875:18;;109266:37:0::1;14737:162:1::0;109266:37:0::1;109316:9;:19:::0;;;109369:10:::1;::::0;109392::::1;::::0;;109404:12:::1;::::0;109353:64:::1;::::0;;109369:10;;;::::1;;;8811:14:1::0;8804:22;8786:41;;8843:18;;;8836:34;;;8886:18;;;8879:34;8944:2;8929:18;;8922:34;-1:-1:-1;;;;;;;;;;;109353:64:0;8773:3:1;8758:19;109353:64:0::1;8740:222:1::0;108785:314:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;108898:4:::1;108889:6;:13;:40;;;;;98585:12;108906:6;:23;108889:40;108881:70;;;::::0;-1:-1:-1;;;108881:70:0;;21314:2:1;108881:70:0::1;::::0;::::1;21296:21:1::0;21353:2;21333:18;;;21326:30;-1:-1:-1;;;21372:18:1;;;21365:47;21429:18;;108881:70:0::1;21286:167:1::0;108881:70:0::1;108986:23;98476:2;108986;:23;:::i;:::-;108977:32;::::0;:6;:32:::1;:::i;:::-;108964:10;:45:::0;;;109043:10:::1;::::0;109055:9:::1;::::0;109078:12:::1;::::0;109027:64:::1;::::0;;109043:10;;;::::1;;;8811:14:1::0;8804:22;8786:41;;8843:18;;;8836:34;;;;8886:18;;;8879:34;;;;8944:2;8929:18;;8922:34;-1:-1:-1;;;;;;;;;;;109027:64:0;8773:3:1;8758:19;109027:64:0::1;8740:222:1::0;106030:148:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;;;;;;106133:27:0;;;::::1;;::::0;;;:18:::1;:27;::::0;;;;:37;;-1:-1:-1;;106133:37:0::1;::::0;::::1;;::::0;;;::::1;::::0;;106030:148::o;110136:120::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;-1:-1:-1;110227:11:0::1;:21:::0;;-1:-1:-1;;110227:21:0::1;::::0;::::1;;::::0;;;::::1;::::0;;110136:120::o;111357:341::-;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;111477:1:::1;111462:11;:16;;:48;;;;;98585:12;111482:11;:28;111462:48;111454:77;;;::::0;-1:-1:-1;;;111454:77:0;;23767:2:1;111454:77:0::1;::::0;::::1;23749:21:1::0;23806:2;23786:18;;;23779:30;-1:-1:-1;;;23825:18:1;;;23818:46;23881:18;;111454:77:0::1;23739:166:1::0;111454:77:0::1;111571:23;98476:2;111571;:23;:::i;:::-;111557:37;::::0;:11;:37:::1;:::i;86098:201::-:0;85078:13;:11;:13::i;:::-;-1:-1:-1;;;;;86187:22:0;::::1;86179:73;;;::::0;-1:-1:-1;;;86179:73:0;;12186:2:1;86179:73:0::1;::::0;::::1;12168:21:1::0;12225:2;12205:18;;;12198:30;12264:34;12244:18;;;12237:62;-1:-1:-1;;;12315:18:1;;;12308:36;12361:19;;86179:73:0::1;12158:228:1::0;86179:73:0::1;86263:28;86282:8;86263:18;:28::i;116511:188::-:0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;116608:6:::1;116603:89;116618:14:::0;;::::1;116603:89;;;116676:4;116653:10;:20;116664:5;;116670:1;116664:8;;;;;-1:-1:-1::0;;;116664:8:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;116653:20:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;116653:20:0;:27;;-1:-1:-1;;116653:27:0::1;::::0;::::1;;::::0;;;::::1;::::0;;116634:3;::::1;::::0;::::1;:::i;:::-;;;;116603:89;;108479:298:::0;-1:-1:-1;;;;;;;;;;;89126:16:0;89137:4;89126:10;:16::i;:::-;108593:2:::1;108584:6;:11;108576:42;;;::::0;-1:-1:-1;;;108576:42:0;;17820:2:1;108576:42:0::1;::::0;::::1;17802:21:1::0;17859:2;17839:18;;;17832:30;-1:-1:-1;;;17878:18:1;;;17871:48;17936:18;;108576:42:0::1;17792:168:1::0;108576:42:0::1;108644:43;98956:4;108644:24;108661:6;108644:12;;:16;;:24;;;;:::i;94252:238::-:0;94336:22;94344:4;94350:7;94336;:22::i;:::-;94331:152;;94375:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;94375:29:0;;;;;;;;;:36;;-1:-1:-1;;94375:36:0;94407:4;94375:36;;;94458:12;70891:10;70811:98;;94458:12;-1:-1:-1;;;;;94431:40:0;94449:7;-1:-1:-1;;;;;94431:40:0;94443:4;94431:40;;;;;;;;;;94252:238;;:::o;56585:152::-;56655:4;56679:50;56684:3;-1:-1:-1;;;;;56704:23:0;;56679:4;:50::i;89234:204::-;89319:4;-1:-1:-1;;;;;;89343:47:0;;-1:-1:-1;;;89343:47:0;;:87;;-1:-1:-1;;;;;;;;;;63269:40:0;;;89394:36;63160:157;89981:105;90048:30;90059:4;70891:10;90048;:30::i;81373:380::-;-1:-1:-1;;;;;81509:19:0;;81501:68;;;;-1:-1:-1;;;81501:68:0;;22002:2:1;81501:68:0;;;21984:21:1;22041:2;22021:18;;;22014:30;22080:34;22060:18;;;22053:62;-1:-1:-1;;;22131:18:1;;;22124:34;22175:19;;81501:68:0;21974:226:1;81501:68:0;-1:-1:-1;;;;;81588:21:0;;81580:68;;;;-1:-1:-1;;;81580:68:0;;12593:2:1;81580:68:0;;;12575:21:1;12632:2;12612:18;;;12605:30;12671:34;12651:18;;;12644:62;-1:-1:-1;;;12722:18:1;;;12715:32;12764:19;;81580:68:0;12565:224:1;81580:68:0;-1:-1:-1;;;;;81661:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;81713:32;;9113:25:1;;;81713:32:0;;9086:18:1;81713:32:0;;;;;;;81373:380;;;:::o;122479:348::-;122536:5;122533:287;;;122576:8;122557:27;;:16;:27;;;;;;;122599:25;;;;122639;;122533:287;;;122717:9;122697:29;;:17;:29;;;;;;;122741:26;;;;122782;;122479:348;:::o;122839:187::-;122897:5;122894:125;;;122929:16;122918:27;:8;:27;;;;;122894:125;;;122990:17;122978:29;:9;:29;;;;;122839:187;:::o;117625:866::-;117771:13;:49;;-1:-1:-1;;;;;;117771:49:0;-1:-1:-1;;;;;117771:49:0;;;;;;;;117919:23;;;-1:-1:-1;;;117919:23:0;;;;:21;;:23;;;;;;;;;;;;;;;117771:49;117919:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;117901:53:0;;117963:4;117970:13;;;;;;;;;-1:-1:-1;;;;;117970:13:0;-1:-1:-1;;;;;117970:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117901:90;;-1:-1:-1;;;;;;117901:90:0;;;;;;;-1:-1:-1;;;;;7045:15:1;;;117901:90:0;;;7027:34:1;7097:15;;7077:18;;;7070:43;6962:18;;117901:90:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117887:11;:104;;-1:-1:-1;;;;;;117887:104:0;-1:-1:-1;;;;;117887:104:0;;;;;;;;;117998:39;;-1:-1:-1;117998:11:0;:39::i;:::-;118154:13;;-1:-1:-1;;;;;118154:13:0;118125:44;;;;:20;:44;;;;;:51;;-1:-1:-1;;118125:51:0;118172:4;118125:51;;;118189:60;118198:7;85265:6;;-1:-1:-1;;;;;85265:6:0;85192:87;;118198:7;118215:13;;-1:-1:-1;;;;;118215:13:0;-1:-1:-1;;118189:8:0;:60::i;:::-;118274:13;;;;;;;;;-1:-1:-1;;;;;118274:13:0;-1:-1:-1;;;;;118274:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118313:13;;118260:87;;-1:-1:-1;;;118260:87:0;;-1:-1:-1;;;;;118313:13:0;;;118260:87;;;7298:51:1;-1:-1:-1;;7365:18:1;;;7358:34;118260:44:0;;;;;7271:18:1;;118260:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;118372:13;;;;;;;;;-1:-1:-1;;;;;118372:13:0;-1:-1:-1;;;;;118372:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118358:78;;-1:-1:-1;;;118358:78:0;;118411:4;118358:78;;;7298:51:1;-1:-1:-1;;7365:18:1;;;7358:34;-1:-1:-1;;;;;118358:44:0;;;;;;;7271:18:1;;118358:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;118450:33:0;;-1:-1:-1;;;;;118450:33:0;;;;;;;;117625:866;:::o;82044:453::-;82179:24;82206:25;82216:5;82223:7;82206:9;:25::i;:::-;82179:52;;-1:-1:-1;;82246:16:0;:37;82242:248;;82328:6;82308:16;:26;;82300:68;;;;-1:-1:-1;;;82300:68:0;;13332:2:1;82300:68:0;;;13314:21:1;13371:2;13351:18;;;13344:30;13410:31;13390:18;;;13383:59;13459:18;;82300:68:0;13304:179:1;82300:68:0;82412:51;82421:5;82428:7;82456:6;82437:16;:25;82412:8;:51::i;123245:1484::-;-1:-1:-1;;;;;123377:18:0;;123369:42;;;;-1:-1:-1;;;123369:42:0;;16468:2:1;123369:42:0;;;16450:21:1;16507:2;16487:18;;;16480:30;-1:-1:-1;;;16526:18:1;;;16519:41;16577:18;;123369:42:0;16440:161:1;123369:42:0;-1:-1:-1;;;;;123430:16:0;;123422:38;;;;-1:-1:-1;;;123422:38:0;;19893:2:1;123422:38:0;;;19875:21:1;19932:1;19912:18;;;19905:29;-1:-1:-1;;;19950:18:1;;;19943:39;19999:18;;123422:38:0;19865:158:1;123422:38:0;123475:11;123471:93;;123503:28;123519:4;123525:2;123529:1;123503:15;:28::i;:::-;123546:7;;123471:93;-1:-1:-1;;;;;123579:16:0;;;;;;:10;:16;;;;;;;;;:34;;-1:-1:-1;;;;;;123599:14:0;;;;;;:10;:14;;;;;;;;123579:34;123576:113;;;123621:35;123639:4;123645:2;123649:6;123621:17;:35::i;123576:113::-;123706:17;;;;123701:398;;123782:24;:22;:24::i;:::-;123873:27;123883:4;123889:2;123893:6;123873:9;:27::i;:::-;123976;123986:4;123992:2;123996:6;123976:9;:27::i;:::-;124060;124078:4;124084:2;124060:17;:27::i;:::-;124188:17;;-1:-1:-1;;;;;124307:24:0;;124172:12;124307:24;;;:18;:24;;;;;;124188:17;;;;124187:18;;124307:24;;:50;;-1:-1:-1;;;;;;124335:22:0;;;;;;:18;:22;;;;;;;;124307:50;124303:99;;;-1:-1:-1;124385:5:0;124303:99;124680:41;124695:4;124701:2;124705:6;124713:7;124680:14;:41::i;118635:143::-;-1:-1:-1;;;;;118701:14:0;;;;;;;:8;:14;;;;;;;;:22;;;;;-1:-1:-1;;118701:22:0;;;;;;;;118736:20;:26;;;;;;:34;;;;;;;;118635:143::o;96870:169::-;96958:31;96975:4;96981:7;96958:16;:31::i;:::-;97000:18;;;;:12;:18;;;;;:31;;97023:7;97000:22;:31::i;97133:174::-;97222:32;97240:4;97246:7;97222:17;:32::i;:::-;97265:18;;;;:12;:18;;;;;:34;;97291:7;97265:25;:34::i;78654:671::-;-1:-1:-1;;;;;78785:18:0;;78777:68;;;;-1:-1:-1;;;78777:68:0;;20230:2:1;78777:68:0;;;20212:21:1;20269:2;20249:18;;;20242:30;20308:34;20288:18;;;20281:62;-1:-1:-1;;;20359:18:1;;;20352:35;20404:19;;78777:68:0;20202:227:1;78777:68:0;-1:-1:-1;;;;;78864:16:0;;78856:64;;;;-1:-1:-1;;;78856:64:0;;10436:2:1;78856:64:0;;;10418:21:1;10475:2;10455:18;;;10448:30;10514:34;10494:18;;;10487:62;-1:-1:-1;;;10565:18:1;;;10558:33;10608:19;;78856:64:0;10408:225:1;78856:64:0;-1:-1:-1;;;;;79006:15:0;;78984:19;79006:15;;;;;;;;;;;79040:21;;;;79032:72;;;;-1:-1:-1;;;79032:72:0;;14022:2:1;79032:72:0;;;14004:21:1;14061:2;14041:18;;;14034:30;14100:34;14080:18;;;14073:62;-1:-1:-1;;;14151:18:1;;;14144:36;14197:19;;79032:72:0;13994:228:1;79032:72:0;-1:-1:-1;;;;;79140:15:0;;;:9;:15;;;;;;;;;;;79158:20;;;79140:38;;79200:13;;;;;;;;:23;;79172:6;;79140:9;79200:23;;79172:6;;79200:23;:::i;:::-;;;;;;;;79256:2;-1:-1:-1;;;;;79241:26:0;79250:4;-1:-1:-1;;;;;79241:26:0;;79260:6;79241:26;;;;9113:25:1;;9101:2;9086:18;;9068:76;79241:26:0;;;;;;;;79280:37;118497:130;85357:132;85265:6;;-1:-1:-1;;;;;85265:6:0;70891:10;85421:23;85413:68;;;;-1:-1:-1;;;85413:68:0;;18167:2:1;85413:68:0;;;18149:21:1;;;18186:18;;;18179:30;18245:34;18225:18;;;18218:62;18297:18;;85413:68:0;18139:182:1;86459:191:0;86552:6;;;-1:-1:-1;;;;;86569:17:0;;;-1:-1:-1;;;;;;86569:17:0;;;;;;;86602:40;;86552:6;;;86569:17;86552:6;;86602:40;;86533:16;;86602:40;86459:191;;:::o;120341:409::-;99048:2;120427:3;:17;;120419:41;;;;-1:-1:-1;;;120419:41:0;;16128:2:1;120419:41:0;;;16110:21:1;16167:2;16147:18;;;16140:30;-1:-1:-1;;;16186:18:1;;;16179:41;16237:18;;120419:41:0;16100:161:1;120419:41:0;120484:5;120481:262;;;120537:8;:21;;120505:16;:53;120573:27;;;120481:262;;;-1:-1:-1;120666:9:0;:22;;120633:17;:55;120703:28;120341:409::o;120762:446::-;99048:2;120857:12;:26;;120849:50;;;;-1:-1:-1;;;120849:50:0;;15448:2:1;120849:50:0;;;15430:21:1;15487:2;15467:18;;;15460:30;-1:-1:-1;;;15506:18:1;;;15499:41;15557:18;;120849:50:0;15420:161:1;120849:50:0;120924:5;120921:280;;;120977:21;;;120945:29;:53;121013:36;;;120921:280;;;-1:-1:-1;121115:22:0;;;121082:30;:55;121152:37;120762:446::o;57881:158::-;57955:7;58006:22;58010:3;58022:5;58006:3;:22::i;118790:148::-;-1:-1:-1;;;;;118858:24:0;;;;;;;:18;:24;;;;;;;;:29;;;;;-1:-1:-1;;118858:29:0;;;;;;;;118899:20;:26;;;;;;:31;;;;;;;;118790:148::o;119233:248::-;-1:-1:-1;;;;;119307:18:0;;119299:37;;;;-1:-1:-1;;;119299:37:0;;16808:2:1;119299:37:0;;;16790:21:1;16847:1;16827:18;;;16820:29;-1:-1:-1;;;16865:18:1;;;16858:36;16911:18;;119299:37:0;16780:155:1;119299:37:0;119363:22;;119347:46;;-1:-1:-1;;;;;119363:22:0;;119347:15;:46::i;:::-;119408:22;:29;;-1:-1:-1;;;;;;119408:29:0;-1:-1:-1;;;;;119408:29:0;;;;;119446:27;119408:29;-1:-1:-1;119446:15:0;:27::i;112749:119::-;112793:11;:18;;-1:-1:-1;;112793:18:0;;;;;112829:31;;;-1:-1:-1;8391:41:1;;;8463:2;8448:18;;8441:50;;;8507:18;;;8500:50;112829:31:0;;;;8379:2:1;112829:31:0;;;;;;;112749:119::o;57410:117::-;57473:7;57500:19;57508:3;52894:18;;52811:109;31805:98;31863:7;31890:5;31894:1;31890;:5;:::i;32204:98::-;32262:7;32289:5;32293:1;32289;:5;:::i;50500:414::-;50563:4;52693:19;;;:12;;;:19;;;;;;50580:327;;-1:-1:-1;50623:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;50806:18;;50784:19;;;:12;;;:19;;;;;;:40;;;;50839:11;;50580:327;-1:-1:-1;50890:5:0;50883:12;;90376:505;90465:22;90473:4;90479:7;90465;:22::i;:::-;90460:414;;90653:41;90681:7;-1:-1:-1;;;;;90653:41:0;90691:2;90653:19;:41::i;:::-;90767:38;90795:4;90802:2;90767:19;:38::i;:::-;90558:270;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;90558:270:0;;;;;;;;;;-1:-1:-1;;;90504:358:0;;;;;;;:::i;124735:1163::-;124817:12;98956:4;124841:13;;124832:6;:22;;;;:::i;:::-;:38;;;;:::i;:::-;124817:53;-1:-1:-1;124875:13:0;124891;124817:53;124891:6;:13;:::i;:::-;124875:29;;124917:42;124933:4;124947;124954;124917:15;:42::i;:::-;124970:32;124986:4;124992:2;124996:5;124970:15;:32::i;:::-;125015:17;125047:12;125074;125105;125112:4;125105:6;:12::i;:::-;125101:564;;;125170:8;:21;125146;;:45;;125170:21;125146:45;:::i;:::-;125134:57;-1:-1:-1;125210:13:0;;125206:170;;125251:21;;:72;;125322:1;125251:72;;;125286:21;;125310:9;;125279:28;;:4;:28;:::i;:::-;:40;;;;:::i;:::-;125244:79;-1:-1:-1;125349:11:0;125244:79;125349:4;:11;:::i;:::-;125342:18;;125206:170;125101:564;;;125445:9;:22;125420;;:47;;125445:22;125420:47;:::i;:::-;125408:59;-1:-1:-1;125486:13:0;;125482:172;;125527:22;;:74;;125600:1;125527:74;;;125563:22;;125588:9;;125556:29;;:4;:29;:::i;:::-;:41;;;;:::i;:::-;125520:81;-1:-1:-1;125627:11:0;125520:81;125627:4;:11;:::i;:::-;125620:18;;125482:172;125681:13;;125677:213;;125732:4;125711:17;;:25;;;;;;;:::i;:::-;;;;;;;;125772:4;125751:17;;:25;;;;;;;:::i;:::-;;;;-1:-1:-1;;125791:15:0;:36;;125823:4;;125791:15;:28;;:36;;125823:4;;125791:36;:::i;:::-;;;;-1:-1:-1;;125842:28:0;:36;;125874:4;;125842:28;;;:36;;125874:4;;125842:36;:::i;:::-;;;;-1:-1:-1;;125677:213:0;124735:1163;;;;;;;;:::o;125906:473::-;125963:13;;;;;;;125959:413;;;126036:15;126009:11;;126023:9;126009:23;;;;:::i;:::-;125997:8;;:36;;;;:::i;:::-;:54;125993:368;;;126134:13;:21;;-1:-1:-1;;126134:21:0;;;126254:23;98476:2;126254;:23;:::i;:::-;126239:38;;:12;:38;:::i;:::-;126224:12;:53;126331:14;:12;:14::i;126877:1925::-;127449:10;;;;;;;127445:1350;;;127509:31;127523:4;127529:2;127533:6;127509:13;:31::i;:::-;127562:13;;;;;;;127561:14;;:56;;-1:-1:-1;;;;;;127581:16:0;;;;;;:10;:16;;;;;;;;127580:17;:36;;;;-1:-1:-1;;;;;;127602:14:0;;;;;;:10;:14;;;;;;;;127601:15;127580:36;127557:285;;;127646:11;;;;;;;127638:33;;;;-1:-1:-1;;;127638:33:0;;17483:2:1;127638:33:0;;;17465:21:1;17522:1;17502:18;;;17495:29;-1:-1:-1;;;17540:18:1;;;17533:39;17589:18;;127638:33:0;17455:158:1;127638:33:0;127698:11;;;;;:27;;;127713:12;127720:4;127713:6;:12::i;:::-;127698:42;;;;127729:11;127737:2;127729:7;:11::i;:::-;127690:68;;;;-1:-1:-1;;;127690:68:0;;19206:2:1;127690:68:0;;;19188:21:1;19245:2;19225:18;;;19218:30;-1:-1:-1;;;19264:18:1;;;19257:43;19317:18;;127690:68:0;19178:163:1;127690:68:0;127908:12;127915:4;127908:6;:12::i;:::-;127904:253;;;127975:16;;127958:13;127968:2;127958:9;:13::i;:::-;127949:22;;:6;:22;:::i;:::-;:42;;127941:71;;;;-1:-1:-1;;;127941:71:0;;19548:2:1;127941:71:0;;;19530:21:1;19587:2;19567:18;;;19560:30;-1:-1:-1;;;19606:18:1;;;19599:46;19662:18;;127941:71:0;19520:166:1;127941:71:0;127904:253;;;128038:11;128046:2;128038:7;:11::i;:::-;128034:123;;128104:16;;128087:13;128097:2;128087:9;:13::i;:::-;128078:22;;:6;:22;:::i;:::-;:42;;128070:71;;;;-1:-1:-1;;;128070:71:0;;19548:2:1;128070:71:0;;;19530:21:1;19587:2;19567:18;;;19560:30;-1:-1:-1;;;19606:18:1;;;19599:46;19662:18;;128070:71:0;19520:166:1;128070:71:0;128208:11;128216:2;128208:7;:11::i;:::-;128204:580;;;128307:15;128273:29;99243:1;128293:9;128273:29;:::i;:::-;-1:-1:-1;;;;;128250:19:0;;;;;;:13;:19;;;;;;:53;;;;:::i;:::-;128249:73;128240:95;;;;-1:-1:-1;;;128240:95:0;;;;;;;:::i;128204:580::-;128361:12;128368:4;128361:6;:12::i;:::-;128357:427;;;128458:15;128424:29;99243:1;128444:9;128424:29;:::i;:::-;-1:-1:-1;;;;;128404:16:0;;;;;;:12;:16;;;;;;:50;;;;:::i;128357:427::-;128629:15;128595:29;99243:1;128615:9;128595:29;:::i;:::-;-1:-1:-1;;;;;128572:19:0;;;;;;:13;:19;;;;;;:53;;;;:::i;:::-;128571:73;128562:95;;;;-1:-1:-1;;;128562:95:0;;;;;;;:::i;:::-;128740:15;128706:29;99243:1;128726:9;128706:29;:::i;:::-;-1:-1:-1;;;;;128686:16:0;;;;;;:12;:16;;;;;;:50;;;;:::i;:::-;128685:70;128676:92;;;;-1:-1:-1;;;128676:92:0;;;;;;;:::i;129113:1124::-;129482:10;;;;;;;129478:752;;;98956:4;129545:9;;129529:13;74379:12;;74291:108;;129529:13;:25;;;;:::i;:::-;:41;;;;:::i;:::-;129519:6;:52;129511:75;;;;-1:-1:-1;;;129511:75:0;;22747:2:1;129511:75:0;;;22729:21:1;22786:2;22766:18;;;22759:30;-1:-1:-1;;;22805:18:1;;;22798:40;22855:18;;129511:75:0;22719:160:1;129511:75:0;129651:11;129659:2;129651:7;:11::i;:::-;129648:566;;;129685:19;129707:15;129717:4;129707:9;:15::i;:::-;129685:37;;129903:10;;129888:11;:25;129885:125;;129956:17;129971:1;129956:11;:17;:::i;:::-;129946:6;:28;129938:52;;;;-1:-1:-1;;;129938:52:0;;15788:2:1;129938:52:0;;;15770:21:1;15827:2;15807:18;;;15800:30;-1:-1:-1;;;15846:18:1;;;15839:41;15897:18;;129938:52:0;15760:161:1;129938:52:0;130170:15;130141:12;;130156:9;130141:24;;;;:::i;:::-;-1:-1:-1;;;;;130118:19:0;;;;;;:13;:19;;;;;;:48;;;;:::i;:::-;130117:68;130108:90;;;;-1:-1:-1;;;130108:90:0;;9739:2:1;130108:90:0;;;9721:21:1;9778:1;9758:18;;;9751:29;-1:-1:-1;;;9796:18:1;;;9789:38;9844:18;;130108:90:0;9711:157:1;131951:395:0;132044:17;;;;132043:18;:48;;;;;132079:12;132086:4;132079:6;:12::i;:::-;132078:13;132043:48;:87;;;;-1:-1:-1;132108:22:0;;;;;;;132043:87;:129;;;;-1:-1:-1;;;;;;132148:24:0;;;;;;:18;:24;;;;;;;;132147:25;132043:129;:169;;;;-1:-1:-1;;;;;;132190:22:0;;;;;;:18;:22;;;;;;;;132189:23;132043:169;132025:314;;;132239:17;:24;;-1:-1:-1;;132239:24:0;132259:4;132239:24;;;132269;:22;:24::i;:::-;132308:17;:25;;-1:-1:-1;;132308:25:0;;;131951:395;;:::o;133546:1171::-;133654:10;133667:14;133674:6;133667;:14::i;:::-;133654:27;;133694:12;133725:7;133721:588;;;133749:30;133782:25;133793:6;133801:5;133782:10;:25::i;:::-;133749:58;;133856:11;:22;;;133831:11;:22;;;:47;;;;:::i;:::-;133824:54;-1:-1:-1;133898:8:0;;133895:403;;133950:11;:22;;;133929:17;;:43;;;;;;;:::i;:::-;;;;-1:-1:-1;;134012:22:0;;;;133991:17;:43;;:17;;:43;;134012:22;;133991:43;:::i;:::-;;;;-1:-1:-1;;134087:22:0;;;;134055:15;:54;;:28;;:54;;134087:22;;134055:54;:::i;:::-;;;;-1:-1:-1;;134160:22:0;;;;134128:28;:54;;:28;;:54;;134160:22;;134128:54;:::i;:::-;;;;-1:-1:-1;134203:44:0;;-1:-1:-1;134219:6:0;134235:4;134242;134203:15;:44::i;:::-;134268:14;134278:4;134268:14;;:::i;:::-;;;133895:403;133721:588;;134325:5;134321:332;;;-1:-1:-1;;;;;134347:23:0;;;;;;:12;:23;;;;;134373:15;134347:41;;134321:332;;;134409:18;134417:9;134409:7;:18::i;:::-;134406:247;;;-1:-1:-1;;;;;134444:21:0;;;;;;:13;:21;;;;;134468:15;134444:39;;134406:247;;;-1:-1:-1;;;;;134546:23:0;;;;;;;:12;:23;;;;;;;;134572:15;134546:41;;;;134602:21;;;;;:13;:21;;;;;:39;134406:247;134665:42;134681:6;134689:9;134700:6;134665:15;:42::i;:::-;133546:1171;;;;;;:::o;94670:239::-;94754:22;94762:4;94768:7;94754;:22::i;:::-;94750:152;;;94825:5;94793:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;94793:29:0;;;;;;;;;;:37;;-1:-1:-1;;94793:37:0;;;94850:40;70891:10;;94793:12;;94850:40;;94825:5;94850:40;94670:239;;:::o;56913:158::-;56986:4;57010:53;57018:3;-1:-1:-1;;;;;57038:23:0;;57010:7;:53::i;53274:120::-;53341:7;53368:3;:11;;53380:5;53368:18;;;;;;-1:-1:-1;;;53368:18:0;;;;;;;;;;;;;;;;;53361:25;;53274:120;;;;:::o;65055:451::-;65130:13;65156:19;65188:10;65192:6;65188:1;:10;:::i;:::-;:14;;65201:1;65188:14;:::i;:::-;65178:25;;;;;;-1:-1:-1;;;65178:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;65178:25:0;;65156:47;;-1:-1:-1;;;65214:6:0;65221:1;65214:9;;;;;;-1:-1:-1;;;65214:9:0;;;;;;;;;;;;:15;-1:-1:-1;;;;;65214:15:0;;;;;;;;;-1:-1:-1;;;65240:6:0;65247:1;65240:9;;;;;;-1:-1:-1;;;65240:9:0;;;;;;;;;;;;:15;-1:-1:-1;;;;;65240:15:0;;;;;;;;-1:-1:-1;65271:9:0;65283:10;65287:6;65283:1;:10;:::i;:::-;:14;;65296:1;65283:14;:::i;:::-;65271:26;;65266:135;65303:1;65299;:5;65266:135;;;-1:-1:-1;;;65351:5:0;65359:3;65351:11;65338:25;;;;;-1:-1:-1;;;65338:25:0;;;;;;;;;;;;65326:6;65333:1;65326:9;;;;;;-1:-1:-1;;;65326:9:0;;;;;;;;;;;;:37;-1:-1:-1;;;;;65326:37:0;;;;;;;;-1:-1:-1;65388:1:0;65378:11;;;;;65306:3;;;:::i;:::-;;;65266:135;;;-1:-1:-1;65419:10:0;;65411:55;;;;-1:-1:-1;;;65411:55:0;;10075:2:1;65411:55:0;;;10057:21:1;;;10094:18;;;10087:30;10153:34;10133:18;;;10126:62;10205:18;;65411:55:0;10047:182:1;119493:164:0;-1:-1:-1;;;;;119635:14:0;119545:4;119635:14;;;:8;:14;;;;;;;;;119493:164::o;119838:491::-;119932:12;119939:4;119932:6;:12::i;:::-;119928:394;;;119977:12;;119967:6;:22;;:50;;;-1:-1:-1;;;;;;119993:24:0;;;;;;:20;:24;;;;;;;;119967:50;119959:75;;;;-1:-1:-1;;;119959:75:0;;17142:2:1;119959:75:0;;;17124:21:1;17181:2;17161:18;;;17154:30;-1:-1:-1;;;17200:18:1;;;17193:42;17252:18;;119959:75:0;17114:162:1;119928:394:0;120057:11;120065:2;120057:7;:11::i;:::-;120053:269;;;120111:12;;120101:6;:22;;:52;;;-1:-1:-1;;;;;;120127:26:0;;;;;;:20;:26;;;;;;;;120101:52;120093:78;;;;-1:-1:-1;;;120093:78:0;;21660:2:1;120093:78:0;;;21642:21:1;21699:2;21679:18;;;21672:30;-1:-1:-1;;;21718:18:1;;;21711:43;21771:18;;120093:78:0;21632:163:1;120053:269:0;120225:12;;120215:6;:22;;:82;;;-1:-1:-1;;;;;;120242:26:0;;;;;;:20;:26;;;;;;;;:54;;;;-1:-1:-1;;;;;;120272:24:0;;;;;;:20;:24;;;;;;;;120242:54;120207:103;;;;-1:-1:-1;;;120207:103:0;;10840:2:1;120207:103:0;;;10822:21:1;10879:1;10859:18;;;10852:29;-1:-1:-1;;;10897:18:1;;;10890:38;10945:18;;120207:103:0;10812:157:1;130243:1696:0;130296:23;130322:24;130340:4;130322:9;:24::i;:::-;130296:50;;130359:14;130396:17;;130376;;:37;;;;:::i;:::-;130359:54;-1:-1:-1;130437:20:0;;;:35;;-1:-1:-1;130461:11:0;;130437:35;:59;;;;130485:11;;130476:6;:20;130437:59;130434:73;;;130499:7;;;;130434:73;130521:16;130587:1;130578:6;130558:17;;130540:15;:35;;;;:::i;:::-;:44;;;;:::i;:::-;:48;;;;:::i;:::-;130521:67;-1:-1:-1;130599:26:0;130628:29;:15;130521:67;130628:19;:29::i;:::-;130599:58;-1:-1:-1;130747:21:0;130807:52;130599:58;130853:4;130807:17;:52::i;:::-;130916:22;130941:41;:21;130967:14;130941:25;:41::i;:::-;130916:66;;131018:18;131039:49;131081:6;131039:37;131058:17;;131039:14;:18;;:37;;;;:::i;:49::-;131018:70;-1:-1:-1;131099:12:0;131114:27;131018:70;131114:14;:27;:::i;:::-;131099:42;;131185:1;131165:17;;:21;:33;;;;;131197:1;131190:4;:8;131165:33;131162:484;;;131527:29;131541:8;131551:4;131527:13;:29::i;:::-;131577:63;131592:8;131602:4;131608:31;131630:8;131608:17;;:21;;:31;;;;:::i;:::-;131577:63;;;26691:25:1;;;26747:2;26732:18;;26725:34;;;;26775:18;;;26768:34;26679:2;26664:18;131577:63:0;;;;;;;131162:484;131717:22;;131709:59;;131695:9;;-1:-1:-1;;;;;131717:22:0;;131753:10;;131695:9;131709:59;131695:9;131709:59;131753:10;131717:22;131709:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;131798:17:0;;131784:50;;;26351:25:1;;;26407:2;26392:18;;26385:34;;;26462:14;;26455:22;26435:18;;;26428:50;131694:74:0;;-1:-1:-1;131784:50:0;;26339:2:1;26324:18;131784:50:0;;;;;;;-1:-1:-1;;131898:1:0;131878:17;:21;;;131910:17;:21;-1:-1:-1;;;;;;;130243:1696:0:o;121216:438::-;121286:30;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121286:30:0;121329:27;;;121392:37;121350:6;121423:5;121392:22;:37::i;:::-;121367:22;;;:62;121465:37;121488:6;121496:5;121465:22;:37::i;:::-;121440:22;;;:62;;;121556:22;;;;121545:62;;121440;121545:34;;:6;;:10;:34::i;:::-;:38;;:62::i;:::-;121523:19;;;:84;121216:438;;;;:::o;51090:1420::-;51156:4;51295:19;;;:12;;;:19;;;;;;51331:15;;51327:1176;;51706:21;51730:14;51743:1;51730:10;:14;:::i;:::-;51779:18;;51706:38;;-1:-1:-1;51759:17:0;;51779:22;;51800:1;;51779:22;:::i;:::-;51759:42;;51835:13;51822:9;:26;51818:405;;51869:17;51889:3;:11;;51901:9;51889:22;;;;;;-1:-1:-1;;;51889:22:0;;;;;;;;;;;;;;;;;51869:42;;52043:9;52014:3;:11;;52026:13;52014:26;;;;;;-1:-1:-1;;;52014:26:0;;;;;;;;;;;;;;;;;;;;:38;;;;52128:23;;;:12;;;:23;;;;;:36;;;51818:405;52304:17;;:3;;:17;;;-1:-1:-1;;;52304:17:0;;;;;;;;;;;;;;;;;;;;;;;;;;52399:3;:12;;:19;52412:5;52399:19;;;;;;;;;;;52392:26;;;52442:4;52435:11;;;;;;;51327:1176;52486:5;52479:12;;;;;31448:98;31506:7;31533:5;31537:1;31533;:5;:::i;132354:589::-;132516:16;;;132530:1;132516:16;;;;;;;;132492:21;;132516:16;;;;;;;;;;-1:-1:-1;132516:16:0;132492:40;;132561:4;132543;132548:1;132543:7;;;;;;-1:-1:-1;;;132543:7:0;;;;;;;;;-1:-1:-1;;;;;132543:23:0;;;:7;;;;;;;;;;:23;;;;132587:13;;:20;;;-1:-1:-1;;;132587:20:0;;;;:13;;;;;:18;;:20;;;;;132543:7;;132587:20;;;;;:13;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;132577:4;132582:1;132577:7;;;;;;-1:-1:-1;;;132577:7:0;;;;;;;;;-1:-1:-1;;;;;132577:30:0;;;:7;;;;;;;;;:30;132652:13;;132620:60;;132637:4;;132652:13;132668:11;132620:8;:60::i;:::-;132719:13;;:216;;-1:-1:-1;;;132719:216:0;;-1:-1:-1;;;;;132719:13:0;;;;:64;;:216;;132798:11;;132719:13;;132868:4;;132887:7;;132909:15;;132719:216;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132354:589;;;:::o;132951:514::-;133132:13;;133100:60;;133117:4;;-1:-1:-1;;;;;133132:13:0;133148:11;133100:8;:60::i;:::-;133203:13;;:254;;-1:-1:-1;;;133203:254:0;;-1:-1:-1;;;;;133203:13:0;;;;:29;;133240:9;;133203:254;;133273:4;;133293:11;;133203:13;;;;99311:42;;133431:15;;133203:254;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;132951:514;;:::o;121666:396::-;121748:7;121771:5;121768:287;;;121799:8;:21;:101;;121899:1;121799:101;;;121855:8;:21;121844:52;;98956:4;;121844:33;;:6;;:10;:33::i;:52::-;121792:108;;;;121768:287;121940:9;:22;:103;;122042:1;121940:103;;;121997:9;:22;121986:53;;98956:4;;121986:34;;:6;;:10;:34::i;122070:397::-;122152:7;122175:5;122172:288;;;122203:21;;:101;;122303:1;122203:101;;;122259:21;;122248:52;;98956:4;;122248:33;;:6;;:10;:33::i;122172:288::-;122344:22;;:103;;122446:1;122344:103;;;122401:22;;122390:53;;98956:4;;122390:34;;:6;;:10;:34::i;14:257:1:-;;126:2;114:9;105:7;101:23;97:32;94:2;;;147:6;139;132:22;94:2;191:9;178:23;210:31;235:5;210:31;:::i;276:261::-;;399:2;387:9;378:7;374:23;370:32;367:2;;;420:6;412;405:22;367:2;457:9;451:16;476:31;501:5;476:31;:::i;812:398::-;;;941:2;929:9;920:7;916:23;912:32;909:2;;;962:6;954;947:22;909:2;1006:9;993:23;1025:31;1050:5;1025:31;:::i;:::-;1075:5;-1:-1:-1;1132:2:1;1117:18;;1104:32;1145:33;1104:32;1145:33;:::i;:::-;1197:7;1187:17;;;899:311;;;;;:::o;1215:466::-;;;;1361:2;1349:9;1340:7;1336:23;1332:32;1329:2;;;1382:6;1374;1367:22;1329:2;1426:9;1413:23;1445:31;1470:5;1445:31;:::i;:::-;1495:5;-1:-1:-1;1552:2:1;1537:18;;1524:32;1565:33;1524:32;1565:33;:::i;:::-;1319:362;;1617:7;;-1:-1:-1;;;1671:2:1;1656:18;;;;1643:32;;1319:362::o;1686:392::-;;;1812:2;1800:9;1791:7;1787:23;1783:32;1780:2;;;1833:6;1825;1818:22;1780:2;1877:9;1864:23;1896:31;1921:5;1896:31;:::i;:::-;1946:5;-1:-1:-1;2003:2:1;1988:18;;1975:32;2016:30;1975:32;2016:30;:::i;2083:325::-;;;2212:2;2200:9;2191:7;2187:23;2183:32;2180:2;;;2233:6;2225;2218:22;2180:2;2277:9;2264:23;2296:31;2321:5;2296:31;:::i;:::-;2346:5;2398:2;2383:18;;;;2370:32;;-1:-1:-1;;;2170:238:1:o;2413:665::-;;;2560:2;2548:9;2539:7;2535:23;2531:32;2528:2;;;2581:6;2573;2566:22;2528:2;2626:9;2613:23;2655:18;2696:2;2688:6;2685:14;2682:2;;;2717:6;2709;2702:22;2682:2;2760:6;2749:9;2745:22;2735:32;;2805:7;2798:4;2794:2;2790:13;2786:27;2776:2;;2832:6;2824;2817:22;2776:2;2877;2864:16;2903:2;2895:6;2892:14;2889:2;;;2924:6;2916;2909:22;2889:2;2982:7;2977:2;2967:6;2964:1;2960:14;2956:2;2952:23;2948:32;2945:45;2942:2;;;3008:6;3000;2993:22;2942:2;3044;3036:11;;;;;3066:6;;-1:-1:-1;2518:560:1;;-1:-1:-1;;;;2518:560:1:o;3083:251::-;;3192:2;3180:9;3171:7;3167:23;3163:32;3160:2;;;3213:6;3205;3198:22;3160:2;3257:9;3244:23;3276:28;3298:5;3276:28;:::i;3339:255::-;;3459:2;3447:9;3438:7;3434:23;3430:32;3427:2;;;3480:6;3472;3465:22;3427:2;3517:9;3511:16;3536:28;3558:5;3536:28;:::i;3599:190::-;;3711:2;3699:9;3690:7;3686:23;3682:32;3679:2;;;3732:6;3724;3717:22;3679:2;-1:-1:-1;3760:23:1;;3669:120;-1:-1:-1;3669:120:1:o;3794:325::-;;;3923:2;3911:9;3902:7;3898:23;3894:32;3891:2;;;3944:6;3936;3929:22;3891:2;3985:9;3972:23;3962:33;;4045:2;4034:9;4030:18;4017:32;4058:31;4083:5;4058:31;:::i;4124:258::-;;;4253:2;4241:9;4232:7;4228:23;4224:32;4221:2;;;4274:6;4266;4259:22;4221:2;-1:-1:-1;;4302:23:1;;;4372:2;4357:18;;;4344:32;;-1:-1:-1;4211:171:1:o;4387:306::-;;4498:2;4486:9;4477:7;4473:23;4469:32;4466:2;;;4519:6;4511;4504:22;4466:2;4550:23;;-1:-1:-1;;;;;;4602:32:1;;4592:43;;4582:2;;4654:6;4646;4639:22;4893:387;;;;5036:2;5024:9;5015:7;5011:23;5007:32;5004:2;;;5057:6;5049;5042:22;5004:2;5098:9;5085:23;5075:33;;5155:2;5144:9;5140:18;5127:32;5117:42;;5209:2;5198:9;5194:18;5181:32;5222:28;5244:5;5222:28;:::i;:::-;5269:5;5259:15;;;4994:286;;;;;:::o;5285:316::-;;;;5442:2;5430:9;5421:7;5417:23;5413:32;5410:2;;;5463:6;5455;5448:22;5410:2;5497:9;5491:16;5481:26;;5547:2;5536:9;5532:18;5526:25;5516:35;;5591:2;5580:9;5576:18;5570:25;5560:35;;5400:201;;;;;:::o;5816:786::-;;6227:25;6222:3;6215:38;6282:6;6276:13;6298:62;6353:6;6348:2;6343:3;6339:12;6332:4;6324:6;6320:17;6298:62;:::i;:::-;-1:-1:-1;;;6419:2:1;6379:16;;;6411:11;;;6404:40;6469:13;;6491:63;6469:13;6540:2;6532:11;;6525:4;6513:17;;6491:63;:::i;:::-;6574:17;6593:2;6570:26;;6205:397;-1:-1:-1;;;;6205:397:1:o;7403:607::-;-1:-1:-1;;;;;7762:15:1;;;7744:34;;7809:2;7794:18;;7787:34;;;;7852:2;7837:18;;7830:34;;;;7895:2;7880:18;;7873:34;;;;7944:15;;;7938:3;7923:19;;7916:44;7724:3;7976:19;;7969:35;;;;7693:3;7678:19;;7660:350::o;9149:383::-;;9298:2;9287:9;9280:21;9330:6;9324:13;9373:6;9368:2;9357:9;9353:18;9346:34;9389:66;9448:6;9443:2;9432:9;9428:18;9423:2;9415:6;9411:15;9389:66;:::i;:::-;9516:2;9495:15;-1:-1:-1;;9491:29:1;9476:45;;;;9523:2;9472:54;;9270:262;-1:-1:-1;;9270:262:1:o;14227:331::-;14429:2;14411:21;;;14468:1;14448:18;;;14441:29;-1:-1:-1;;;14501:2:1;14486:18;;14479:38;14549:2;14534:18;;14401:157::o;24914:983::-;;25224:3;25213:9;25209:19;25255:6;25244:9;25237:25;25281:2;25319:6;25314:2;25303:9;25299:18;25292:34;25362:3;25357:2;25346:9;25342:18;25335:31;25386:6;25421;25415:13;25452:6;25444;25437:22;25490:3;25479:9;25475:19;25468:26;;25529:2;25521:6;25517:15;25503:29;;25550:4;25563:195;25577:6;25574:1;25571:13;25563:195;;;25642:13;;-1:-1:-1;;;;;25638:39:1;25626:52;;25733:15;;;;25698:12;;;;25674:1;25592:9;25563:195;;;-1:-1:-1;;;;;;;25814:32:1;;;;25809:2;25794:18;;25787:60;-1:-1:-1;;;25878:3:1;25863:19;25856:35;25775:3;25185:712;-1:-1:-1;;;25185:712:1:o;27002:128::-;;27073:1;27069:6;27066:1;27063:13;27060:2;;;27079:18;;:::i;:::-;-1:-1:-1;27115:9:1;;27050:80::o;27135:217::-;;27201:1;27191:2;;-1:-1:-1;;;27226:31:1;;27280:4;27277:1;27270:15;27308:4;27233:1;27298:15;27191:2;-1:-1:-1;27337:9:1;;27181:171::o;27357:453::-;27453:6;27476:5;27490:314;27539:1;27576:2;27566:8;27563:16;27553:2;;27583:5;;;27553:2;27624:4;27619:3;27615:14;27609:4;27606:24;27603:2;;;27633:18;;:::i;:::-;27683:2;27673:8;27669:17;27666:2;;;27698:16;;;;27666:2;27777:17;;;;;27737:15;;27490:314;;;27434:376;;;;;;;:::o;27815:139::-;;27904:44;-1:-1:-1;;27931:8:1;27925:4;27959:922;28043:8;28033:2;;-1:-1:-1;28084:1:1;28098:5;;28033:2;28132:4;28122:2;;-1:-1:-1;28169:1:1;28183:5;;28122:2;28214:4;28232:1;28227:59;;;;28300:1;28295:183;;;;28207:271;;28227:59;28257:1;28248:10;;28271:5;;;28295:183;28332:3;28322:8;28319:17;28316:2;;;28339:18;;:::i;:::-;28395:1;28385:8;28381:16;28372:25;;28423:3;28416:5;28413:14;28410:2;;;28430:18;;:::i;:::-;28463:5;;;28207:271;;28562:2;28552:8;28549:16;28543:3;28537:4;28534:13;28530:36;28524:2;28514:8;28511:16;28506:2;28500:4;28497:12;28493:35;28490:77;28487:2;;;-1:-1:-1;28599:19:1;;;28634:14;;;28631:2;;;28651:18;;:::i;:::-;28684:5;;28487:2;28731:42;28769:3;28759:8;28753:4;28750:1;28731:42;:::i;:::-;28806:6;28801:3;28797:16;28788:7;28785:29;28782:2;;;28817:18;;:::i;:::-;28855:20;;28023:858;-1:-1:-1;;;;28023:858:1:o;28886:168::-;;28992:1;28988;28984:6;28980:14;28977:1;28974:21;28969:1;28962:9;28955:17;28951:45;28948:2;;;28999:18;;:::i;:::-;-1:-1:-1;29039:9:1;;28938:116::o;29059:125::-;;29127:1;29124;29121:8;29118:2;;;29132:18;;:::i;:::-;-1:-1:-1;29169:9:1;;29108:76::o;29189:258::-;29261:1;29271:113;29285:6;29282:1;29279:13;29271:113;;;29361:11;;;29355:18;29342:11;;;29335:39;29307:2;29300:10;29271:113;;;29402:6;29399:1;29396:13;29393:2;;;-1:-1:-1;;29437:1:1;29419:16;;29412:27;29242:205::o;29452:136::-;;29519:5;29509:2;;29528:18;;:::i;:::-;-1:-1:-1;;;29564:18:1;;29499:89::o;29593:380::-;29672:1;29668:12;;;;29715;;;29736:2;;29790:4;29782:6;29778:17;29768:27;;29736:2;29843;29835:6;29832:14;29812:18;29809:38;29806:2;;;29889:10;29884:3;29880:20;29877:1;29870:31;29924:4;29921:1;29914:15;29952:4;29949:1;29942:15;29806:2;;29648:325;;;:::o;29978:135::-;;-1:-1:-1;;30038:17:1;;30035:2;;;30058:18;;:::i;:::-;-1:-1:-1;30105:1:1;30094:13;;30025:88::o;30118:127::-;30179:10;30174:3;30170:20;30167:1;30160:31;30210:4;30207:1;30200:15;30234:4;30231:1;30224:15;30250:131;-1:-1:-1;;;;;30325:31:1;;30315:42;;30305:2;;30371:1;30368;30361:12;30386:118;30472:5;30465:13;30458:21;30451:5;30448:32;30438:2;;30494:1;30491;30484:12

Swarm Source

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