ETH Price: $3,595.42 (+0.89%)
Gas: 5 Gwei

Token

DeepSouth AI (SOUTH)
 

Overview

Max Total Supply

1,000,000 SOUTH

Holders

3,702 ( -0.162%)

Total Transfers

-

Market

Price

$9.65 @ 0.002684 ETH (-2.30%)

Onchain Market Cap

$9,650,000.00

Circulating Supply Market Cap

$0.00

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

DeepSouth AI is an artificial intelligence system that utilizes neuromorphic computing.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
DeepSouthAI

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-01-05
*/

/**
 * @dev This smart contract was developed based on the general
 * OpenZeppelin Contracts guidelines where functions revert instead of
 * returning `false` on failure.
 */

// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

/********************************************************************************************
  LIBRARY
********************************************************************************************/

/**
 * @title Address Library
 *
 * @notice Collection of functions providing utility for interacting with addresses.
 */
library Address {
    // ERROR

    /**
     * @notice Error indicating insufficient balance while performing an operation.
     *
     * @param account Address where the balance is insufficient.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @notice Error indicating an attempt to interact with a contract having empty code.
     *
     * @param target Address of the contract with empty code.
     */
    error AddressEmptyCode(address target);

    /**
     * @notice Error indicating a failed internal call.
     */
    error FailedInnerCall();

    // FUNCTION

    /**
     * @notice Calls a function on a specified address without transferring value.
     *
     * @param target Address on which the function will be called.
     * @param data Encoded data of the function call.
     *
     * @return returndata Result of the function call.
     *
     * @dev The `target` must be a contract address and this function must be calling
     * `target` with `data` not reverting.
     */
    function functionCall(
        address target,
        bytes memory data
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @notice Calls a function on a specified address with a specified value.
     *
     * @param target Address on which the function will be called.
     * @param data Encoded data of the function call.
     * @param value Value to be sent in the call.
     *
     * @return returndata Result of the function call.
     *
     * @dev This function ensure that the calling contract actually have Ether balance
     * of at least `value` and that the called Solidity function is a `payable`. Should
     * throw if caller does have insufficient balance.
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(
            data
        );
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @notice Verifies the result of a function call and handles errors if any.
     *
     * @param target Address on which the function was called.
     * @param success Boolean indicating the success of the function call.
     * @param returndata Result data of the function call.
     *
     * @return Result of the function call or reverts with an appropriate error.
     *
     * @dev This help to verify that a low level call to smart-contract was successful
     * and will reverts if the target was not a contract. For unsuccessful call, this
     * will bubble up the revert reason (falling back to {FailedInnerCall}). Should
     * throw if both the returndata and target.code length are 0 when `success` is true.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @notice Reverts with decoded revert data or FailedInnerCall if no revert
     * data is available.
     *
     * @param returndata Result data of a failed function call.
     *
     * @dev Should throw if returndata length is 0.
     */
    function _revert(bytes memory returndata) private pure {
        if (returndata.length > 0) {
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

/**
 * @title SafeERC20 Library
 *
 * @notice Collection of functions providing utility for safe operations with
 * ERC20 tokens.
 *
 * @dev This is mainly for the usage of token 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 where non-reverting calls are assumed
 * to be a successful transaction.
 */
library SafeERC20 {
    // LIBRARY

    using Address for address;

    // ERROR

    /**
     * @notice Error indicating a failed operation during an ERC-20 token transfer.
     *
     * @param token Address of the token contract.
     */
    error SafeERC20FailedOperation(address token);

    // FUNCTION

    /**
     * @notice Safely transfers tokens.
     *
     * @param token ERC20 token interface.
     * @param to Address to which the tokens will be transferred.
     * @param value Amount of tokens to be transferred.
     *
     * @dev Transfer `value` amount of `token` from the calling contract to `to` where
     * non-reverting calls are assumed to be successful if `token` returns no value.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @notice Calls a function on a token contract and reverts if the operation fails.
     *
     * @param token ERC20 token interface.
     * @param data Encoded data of the function call.
     *
     * @dev This imitates a Solidity high-level call such as a regular function call to
     * a contract while relaxing the requirement on the return value.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }
}

/********************************************************************************************
  INTERFACE
********************************************************************************************/

/**
 * @title Router Interface
 *
 * @notice Interface of the Router contract, providing functions to interact with
 * Router contract that is derived from Uniswap V2 Router.
 *
 * @dev See https://docs.uniswap.org/contracts/v2/reference/smart-contracts/router-02
 */
interface IRouter {

    // FUNCTION

    /**
     * @notice Get the address of the Wrapped Ether (WETH) token.
     *
     * @return The address of the WETH token.
     */
    function WETH() external pure returns (address);

    /**
     * @notice Get the address of the linked Factory contract.
     *
     * @return The address of the Factory contract.
     */
    function factory() external pure returns (address);

    /**
     * @notice Swaps an exact amount of tokens for ETH, supporting
     * tokens that implement fee-on-transfer mechanisms.
     *
     * @param amountIn The exact amount of input tokens for the swap.
     * @param amountOutMin The minimum acceptable amount of ETH to receive in the swap.
     * @param path An array of token addresses representing the token swap path.
     * @param to The recipient address that will receive the swapped ETH.
     * @param deadline The timestamp by which the transaction must be executed to be
     * considered valid.
     *
     * @dev This function swaps a specific amount of tokens for ETH on a specified path,
     * ensuring a minimum amount of output ETH.
     */
    function swapExactTokensForETHSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external;

    /**
     * @notice Swaps a precise amount of ETH for tokens, supporting tokens with fee-on-transfer mechanisms.
     *
     * @param amountOutMin The minimum acceptable amount of output tokens expected from the swap.
     * @param path An array of token addresses representing the token swap path.
     * @param to The recipient address that will receive the swapped tokens.
     * @param deadline The timestamp by which the transaction must be executed to be considered valid.
     *
     * @dev This function performs a direct swap of a specified amount of ETH for tokens based on the provided
     * path and minimum acceptable output token amount.
     */
    function swapExactETHForTokensSupportingFeeOnTransferTokens(uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external payable;
}

/**
 * @title Factory Interface
 *
 * @notice Interface of the Factory contract, providing functions to interact with
 * Factory contract that is derived from Uniswap V2 Factory.
 *
 * @dev See https://docs.uniswap.org/contracts/v2/reference/smart-contracts/factory
 */
interface IFactory {

    // FUNCTION

    /**
     * @notice Create a new token pair for two given tokens on Uniswap V2-based factory.
     *
     * @param tokenA The address of the first token.
     * @param tokenB The address of the second token.
     *
     * @return pair The address of the created pair for the given tokens.
     */
    function createPair(address tokenA, address tokenB) external returns (address pair);

    /**
     * @notice Get the address of the pair for two tokens on the decentralized exchange.
     *
     * @param tokenA The address of the first token.
     * @param tokenB The address of the second token.
     *
     * @return pair The address of the pair corresponding to the provided tokens.
     */
    function getPair(address tokenA, address tokenB) external view returns (address pair);
}

/**
 * @title Pair Interface
 *
 * @notice Interface of the Pair contract in a decentralized exchange based on the
 * Pair contract that is derived from Uniswap V2 Pair.
 *
 * @dev See https://docs.uniswap.org/contracts/v2/reference/smart-contracts/pair
 */
interface IPair {

    // FUNCTION

    /**
     * @notice Get the address of the first token in the pair.
     *
     * @return The address of the first token.
     */
    function token0() external view returns (address);

    /**
     * @notice Get the address of the second token in the pair.
     *
     * @return The address of the second token.
     */
    function token1() external view returns (address);
}

/**
 * @title ERC20 Token Standard Interface
 *
 * @notice Interface of the ERC-20 standard token as defined in the ERC.
 *
 * @dev See https://eips.ethereum.org/EIPS/eip-20
 */
interface IERC20 {

    // EVENT

    /**
     * @notice Emitted when `value` tokens are transferred from
     * one account (`from`) to another (`to`).
     *
     * @param from The address tokens are transferred from.
     * @param to The address tokens are transferred to.
     * @param value The amount of tokens transferred.
     *
     * @dev The `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @notice Emitted when the allowance of a `spender` for an `owner`
     * is set by a call to {approve}.
     *
     * @param owner The address allowing `spender` to spend on their behalf.
     * @param spender The address allowed to spend tokens on behalf of `owner`.
     * @param value The allowance amount set for `spender`.
     *
     * @dev The `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    // FUNCTION

    /**
     * @notice Returns the value of tokens in existence.
     *
     * @return The value of the total supply of tokens.
     *
     * @dev This should get the total token supply.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice Returns the value of tokens owned by `account`.
     *
     * @param account The address to query the balance for.
     *
     * @return The token balance of `account`.
     *
     * @dev This should get the token balance of a specific account.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @notice Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * @param to The address to transfer tokens to.
     * @param value The amount of tokens to be transferred.
     *
     * @return A boolean indicating whether the transfer was successful or not.
     *
     * @dev This should transfer tokens to a specified address and emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @notice Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}.
     *
     * @param owner The address allowing `spender` to spend on their behalf.
     * @param spender The address allowed to spend tokens on behalf of `owner`.
     *
     * @return The allowance amount for `spender`.
     *
     * @dev The return value should be zero by default and
     * changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @notice Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * @param spender The address allowed to spend tokens on behalf of the sender.
     * @param value The allowance amount for `spender`.
     *
     * @return A boolean indicating whether the approval was successful or not.
     *
     * @dev This should approve `spender` to spend a specified amount of tokens
     * on behalf of the sender and emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @notice Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's allowance.
     *
     * @param from The address to transfer tokens from.
     * @param to The address to transfer tokens to.
     * @param value The amount of tokens to be transferred.
     *
     * @return A boolean indicating whether the transfer was successful or not.
     *
     * @dev This should transfer tokens from one address to another after
     * spending caller's allowance and emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

/**
 * @title ERC20 Token Metadata Interface
 *
 * @notice Interface for the optional metadata functions of the ERC-20 standard as defined in the ERC.
 *
 * @dev It extends the IERC20 interface. See https://eips.ethereum.org/EIPS/eip-20
 */
interface IERC20Metadata is IERC20 {

    // FUNCTION

    /**
     * @notice Returns the name of the token.
     *
     * @return The name of the token as a string.
     */
    function name() external view returns (string memory);

    /**
     * @notice Returns the symbol of the token.
     *
     * @return The symbol of the token as a string.
     */
    function symbol() external view returns (string memory);

    /**
     * @notice Returns the number of decimals used to display the token.
     *
     * @return The number of decimals as a uint8.
     */
    function decimals() external view returns (uint8);
}

/**
 * @title ERC20 Token Standard Error Interface
 *
 * @notice Interface of the ERC-6093 custom errors that defined common errors
 * related to the ERC-20 standard token functionalities.
 *
 * @dev See https://eips.ethereum.org/EIPS/eip-6093
 */
interface IERC20Errors {

    // ERROR

    /**
     * @notice Error indicating that the `sender` has inssufficient `balance` for the operation.
     *
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     *
     * @dev The `needed` value is required to inform user on the needed amount.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @notice Error indicating that the `sender` is invalid for the operation.
     *
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @notice Error indicating that the `receiver` is invalid for the operation.
     *
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @notice Error indicating that the `spender` does not have enough `allowance` for the operation.
     *
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     *
     * @dev The `needed` value is required to inform user on the needed amount.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @notice Error indicating that the `approver` is invalid for the approval operation.
     *
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @notice Error indicating that the `spender` is invalid for the allowance operation.
     *
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @title Common Error Interface
 *
 * @notice Interface of the common errors not specific to ERC-20 functionalities.
 */
interface ICommonError {

    // ERROR

    /**
     * @notice Error indicating that the `current` address cannot be used in this context.
     *
     * @param current Address used in the context.
     */
    error CannotUseCurrentAddress(address current);

    /**
     * @notice Error indicating that the `current` value cannot be used in this context.
     *
     * @param current Value used in the context.
     */
    error CannotUseCurrentValue(uint256 current);

    /**
     * @notice Error indicating that the `current` state cannot be used in this context.
     *
     * @param current Boolean state used in the context.
     */
    error CannotUseCurrentState(bool current);

    /**
     * @notice Error indicating that the `invalid` address provided is not a valid address for this context.
     *
     * @param invalid Address used in the context.
     */
    error InvalidAddress(address invalid);

    /**
     * @notice Error indicating that the `invalid` value provided is not a valid value for this context.
     *
     * @param invalid Value used in the context.
     */
    error InvalidValue(uint256 invalid);
}

/********************************************************************************************
  ACCESS
********************************************************************************************/

/**
 * @title Ownable Contract
 *
 * @notice Abstract contract module implementing ownership functionality through
 * inheritance as a basic access control mechanism, where there is an owner account
 * that can be granted exclusive access to specific functions.
 *
 * @dev The initial owner is set to the address provided by the deployer and can
 * later be changed with {transferOwnership}.
 */
abstract contract Ownable {

    // DATA

    address private _owner;

    // MODIFIER

    /**
     * @notice Modifier that allows access only to the contract owner.
     *
     * @dev Should throw if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    // ERROR

    /**
     * @notice Error indicating that the `account` is not authorized to perform an operation.
     *
     * @param account Address used to perform the operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @notice Error indicating that the provided `owner` address is invalid.
     *
     * @param owner Address used to perform the operation.
     *
     * @dev Should throw if called by an invalid owner account such as address(0) as an example.
     */
    error OwnableInvalidOwner(address owner);

    // CONSTRUCTOR

    /**
     * @notice Initializes the contract setting the `initialOwner` address provided by
     * the deployer as the initial owner.
     *
     * @param initialOwner The address to set as the initial owner.
     *
     * @dev Should throw an error if called with address(0) as the `initialOwner`.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    // EVENT

    /**
     * @notice Emitted when ownership of the contract is transferred.
     *
     * @param previousOwner The address of the previous owner.
     * @param newOwner The address of the new owner.
     */
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    // FUNCTION

    /**
     * @notice Get the address of the smart contract owner.
     *
     * @return The address of the current owner.
     *
     * @dev Should return the address of the current smart contract owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @notice Checks if the caller is the owner and reverts if not.
     *
     * @dev Should throw if the sender is not the current owner of the smart contract.
     */
    function _checkOwner() internal view virtual {
        if (owner() != msg.sender) {
            revert OwnableUnauthorizedAccount(msg.sender);
        }
    }

    /**
     * @notice Allows the current owner to renounce ownership and make the
     * smart contract ownerless.
     *
     * @dev This function can only be called by the current owner and will
     * render all `onlyOwner` functions inoperable.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @notice Allows the current owner to transfer ownership of the smart contract
     * to `newOwner` address.
     *
     * @param newOwner The address to transfer ownership to.
     *
     * @dev This function can only be called by the current owner and will render
     * all `onlyOwner` functions inoperable to him/her. Should throw if called with
     * address(0) as the `newOwner`.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @notice Internal function to transfer ownership of the smart contract
     * to `newOwner` address.
     *
     * @param newOwner The address to transfer ownership to.
     *
     * @dev This function replace current owner address stored as _owner with
     * the address of the `newOwner`.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

/********************************************************************************************
  TOKEN
********************************************************************************************/

/**
 * @title DeepSouth AI Token Contract
 *
 * @notice DeepSouth AI is an extended version of ERC-20 standard token that
 * includes additional functionalities for ownership control, trading enabling,
 * and token management.
 *
 * @dev Implements ERC20Metadata, ERC20Errors, and CommonError interfaces, and
 * extends Ownable contract.
 */
contract DeepSouthAI is Ownable, IERC20Metadata, IERC20Errors, ICommonError {

    // LIBRARY

    using SafeERC20 for IERC20;
    using Address for address;

    // DATA

    struct Fee {
        uint256 marketing;
        uint256 total;
    }

    Fee public buyFee = Fee(1000, 1000);
    Fee public sellFee = Fee(1000, 1000);
    Fee public transferFee = Fee(0, 0);
    Fee public collectedFee = Fee(0, 0);
    Fee public redeemedFee = Fee(0, 0);

    IRouter public router = IRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);

    string private constant NAME = "DeepSouth AI";
    string private constant SYMBOL = "SOUTH";

    uint8 private constant DECIMALS = 18;

    uint256 public constant FEEDENOMINATOR = 10_000;

    uint256 public immutable deployTime;

    uint256 private _totalSupply;

    uint256 public tradeStartTime = 0;
    uint256 public tradeStartBlock = 0;
    uint256 public minSwap = 1_000 ether;
    uint256 public maxWalletLimit = 200;

    address public projectOwner = 0x8683b156e02a61924f36E1a88dD1D30964FeB7c5;
    address public marketingReceiver = 0xFFb44e038Cd5bfAD4807FF6ace10793ec9d6330e;

    address public pair;

    bool public tradeEnabled = false;
    bool public isFeeActive = false;
    bool public isFeeLocked = false;
    bool public isReceiverLocked = false;
    bool public isFailsafeLocked = false;
    bool public isWalletLimitLocked = false;
    bool public isWalletLimitActive = false;
    bool public isSwapEnabled = false;
    bool public inSwap = false;

    // MAPPING

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

    mapping(address pair => bool) public isPairLP;
    mapping(address account => bool) public isExemptFee;
    mapping(address account => bool) public isExemptWalletLimit;

    // MODIFIER

    /**
     * @notice Modifier to mark the start and end of a swapping operation.
     */
    modifier swapping() {
        inSwap = true;
        _;
        inSwap = false;
    }

    /**
     * @notice Modifier that allows access only to the project owner or current
     * smart contract owner.
     *
     * @dev Should throw if called by any account other than the project owner or
     * smart contract owner.
     */
    modifier onlyOwnerFailsafe() {
        _checkOwnerFailsafe();
        _;
    }

    // ERROR

    /**
     * @notice Error indicating that an action is attempted before the cooldown period ends.
     *
     * @param cooldownEnd The timestamp when the cooldown period ends.
     * @param timeLeft The time remaining in the cooldown period.
     *
     * @dev The `timeLeft` is required to inform user of the waiting period.
     */
    error WaitForCooldownTimer(uint256 cooldownEnd, uint256 timeLeft);

    /**
     * @notice Error indicating that trading has already been enabled at a specific `timestamp`.
     *
     * @param currentState The current state of trading.
     * @param timestamp The timestamp when trading was enabled.
     *
     * @dev The `currentState` is required to inform user of the current state of trading.
     */
    error TradeAlreadyEnabled(bool currentState, uint256 timestamp);

    /**
     * @notice Error indicating an invalid total fee compared to the maximum allowed.
     *
     * @param current The current total fee.
     * @param max The maximum allowed total fee.
     *
     * @dev The `max` is required to inform user of the maximum value allowed.
     */
    error InvalidTotalFee(uint256 current, uint256 max);

    /**
     * @notice Error indicating an invalid max wallet limit used compared to
     * the minimum value allowed.
     *
     * @param current The current limit used.
     * @param min The minimum allowed wallet limit.
     *
     * @dev The `min` is required to inform user of the minimum value allowed.
     */
    error InvalidWalletLimit(uint256 current, uint256 min);

    /**
     * @notice Error indicating an invalid amount compared to the maximum allowed.
     *
     * @param current The current amount.
     * @param max The maximum allowed wallet limit.
     *
     * @dev The `max` is required to inform user of the maximum value allowed.
     */
    error ExceedWalletLimit(uint256 current, uint256 max);

    /**
     * @notice Error indicating an invalid amount compared to the maximum allowed.
     *
     * @param current The current amount used.
     * @param max The maximum amount allowed to be used.
     *
     * @dev The `max` is required to inform user of the maximum value allowed.
     */
    error CannotRedeemMoreThanAllowedTreshold(uint256 current, uint256 max);

    /**
     * @notice Error indicating that trading has not been enabled yet.
     */
    error TradeNotYetEnabled();

    /**
     * @notice Error indicating that the native token cannot be withdrawn from the smart contract.
     */
    error CannotWithdrawNativeToken();

    /**
     * @notice Error indicating that lock is active for given state and cannot be modified.
     */
    error Locked(string lockType);

    /**
     * @notice Error indicating that the receiver cannot initiate transfer of Ether.
     *
     * @dev Should throw if called by the receiver address.
     */
    error ReceiverCannotInitiateTransferEther();

    /**
     * @notice Error indicating that only a wallet address is allowed to perform the action.
     *
     * @dev Should throw if called to use an address that is not believed to be a wallet.
     */
    error OnlyWalletAddressAllowed();

    // CONSTRUCTOR

    /**
     * @notice Constructs the DeepSouth AI contract and initializes both owner
     * and project owner addresses. Deployer will receive 1,000,000 tokens after
     * the smart contract was deployed.
     *
     * @dev If deployer is not the project owner, then deployer will be exempted
     * from fees along with the project owner and router.
     *
     * IMPORTANT: Project owner should be aware that {enableTrade} function and
     * feature usually would significantly impact the audit score since these
     * functions/features possess the potential for malicious exploitation,
     * which might affect the received score.
     */
    constructor() Ownable (msg.sender) {
        isExemptFee[projectOwner] = true;
        isExemptFee[address(router)] = true;
        isExemptWalletLimit[projectOwner] = true;
        isExemptWalletLimit[address(this)] = true;

        if (projectOwner != msg.sender) {
            isExemptFee[msg.sender] = true;
            isExemptWalletLimit[msg.sender] = true;
        }

        deployTime = block.timestamp;
        _mint(msg.sender, 1_000_000 * 10**DECIMALS);

        pair = IFactory(router.factory()).createPair(address(this), router.WETH());
        isPairLP[pair] = true;
        isExemptWalletLimit[pair] = true;
    }

    // EVENT

    /**
     * @notice Emits when an automatic or manual redemption occurs, distributing fees
     * and redeeming a specific amount.
     *
     * @param marketingFeeDistribution The amount distributed for marketing fees.
     * @param amountToRedeem The total amount being redeemed.
     * @param caller The address that triggered the redemption.
     * @param timestamp The timestamp at which the redemption event occurred.
     */
    event AutoRedeem(uint256 marketingFeeDistribution, uint256 amountToRedeem, address caller, uint256 timestamp);

    /**
     * @notice Emitted when the router address is updated.
     *
     * @param oldRouter The address of the old router.
     * @param newRouter The address of the new router.
     * @param caller The address that triggered the router update.
     * @param timestamp The timestamp when the update occurred.
     */
    event UpdateRouter(address oldRouter, address newRouter, address caller, uint256 timestamp);

    /**
     * @notice Emitted upon setting the status of a specific address type.
     *
     * @param addressType The type of address status being modified.
     * @param account The address of the account whose status is being updated.
     * @param oldStatus The previous exemption status.
     * @param newStatus The new exemption status.
     * @param caller The address that triggered the status update.
     * @param timestamp The timestamp when the update occurred.
     */
    event SetAddressState(string addressType, address account, bool oldStatus, bool newStatus, address caller, uint256 timestamp);

    /**
     * @notice Emitted when trading is enabled for the contract.
     *
     * @param caller The address that triggered the trading enablement.
     * @param timestamp The timestamp when trading was enabled.
     */
    event TradeEnabled(address caller, uint256 timestamp);

    /**
     * @notice Emitted when a lock is applied.
     *
     * @param lockType The type of lock applied.
     * @param caller The address of the caller who applied the lock.
     * @param timestamp The timestamp when the lock was applied.
     */
    event Lock(string lockType, address caller, uint256 timestamp);

    /**
     * @notice Emitted when the minimum swap value is updated.
     *
     * @param oldMinSwap The old minimum swap value before the update.
     * @param newMinSwap The new minimum swap value after the update.
     * @param caller The address of the caller who updated the minimum swap value.
     * @param timestamp The timestamp when the update occurred.
     */
    event UpdateMinSwap(uint256 oldMinSwap, uint256 newMinSwap, address caller, uint256 timestamp);

    /**
     * @notice Emitted when the state of a feature is updated.
     *
     * @param stateType The type of state being updated.
     * @param oldStatus The previous status before the update.
     * @param newStatus The new status after the update.
     * @param caller The address of the caller who updated the state.
     * @param timestamp The timestamp when the update occurred.
     */
    event UpdateState(string stateType, bool oldStatus, bool newStatus, address caller, uint256 timestamp);

    /**
     * @notice Emitted when the value of a limit is updated.
     *
     * @param limitType The type of fee being updated.
     * @param oldLimit The previous marketing fee value before the update.
     * @param newLimit The new marketing fee value after the update.
     * @param caller The address of the caller who updated the fee.
     * @param timestamp The timestamp when the fee update occurred.
     */
    event UpdateLimit(string limitType, uint256 oldLimit, uint256 newLimit, address caller, uint256 timestamp);

    /**
     * @notice Emitted when the value of a fee is updated.
     *
     * @param feeType The type of fee being updated.
     * @param oldMarketingFee The previous marketing fee value before the update.
     * @param newMarketingFee The new marketing fee value after the update.
     * @param caller The address of the caller who updated the fee.
     * @param timestamp The timestamp when the fee update occurred.
     */
    event UpdateFee(string feeType, uint256 oldMarketingFee, uint256 newMarketingFee, address caller, uint256 timestamp);

    /**
     * @notice Emitted upon updating a receiver address.
     *
     * @param receiverType The type of receiver being updated.
     * @param oldReceiver The previous receiver address before the update.
     * @param newReceiver The new receiver address after the update.
     * @param caller The address of the caller who updated the receiver address.
     * @param timestamp The timestamp when the receiver address was updated.
     */
    event UpdateReceiver(string receiverType, address oldReceiver, address newReceiver, address caller, uint256 timestamp);

    // FUNCTION

    /* General */

    /**
     * @notice Allows the contract to receive Ether.
     *
     * @dev This is a required feature to have in order to allow the smart contract
     * to be able to receive ether from the swap.
     */
    receive() external payable {}

    /**
     * @notice Withdraws tokens or Ether from the contract to a specified address.
     *
     * @param tokenAddress The address of the token to withdraw.
     * @param amount The amount of tokens or Ether to withdraw.
     *
     * @dev You need to use address(0) as `tokenAddress` to withdraw Ether and
     * use 0 as `amount` to withdraw the whole balance amount in the smart contract.
     * Anyone can trigger this function to send the fund to the `marketingReceiver`.
     * Only `marketingReceiver` address will not be able to trigger this function to
     * withdraw Ether from the smart contract by himself/herself. Should throw if try
     * to withdraw any amount of native token from the smart contract. Distribution
     * of native token can only be done through autoRedeem function.
     */
    function wTokens(address tokenAddress, uint256 amount) external {
        uint256 toTransfer = amount;
        address receiver = marketingReceiver;

        if (tokenAddress == address(this)) {
            revert CannotWithdrawNativeToken();
        } else if (tokenAddress == address(0)) {
            if (amount == 0) {
                toTransfer = address(this).balance;
            }
            if (msg.sender == receiver) {
                revert ReceiverCannotInitiateTransferEther();
            }
            payable(receiver).transfer(toTransfer);
        } else {
            if (amount == 0) {
                toTransfer = IERC20(tokenAddress).balanceOf(address(this));
            }
            IERC20(tokenAddress).safeTransfer(receiver, toTransfer);
        }
    }

    /**
     * @notice Enables trading functionality for the token contract.
     *
     * @dev Should trade is not enabled, if ownership is set and the sender is not the owner,
     * users can trigger it 30 days after deployment. If ownership is not set or contract
     * has been renounced before enable trade, users can trigger it 15 days after deployment.
     * Other than these, it validates the sender's authorization based on the contract
     * deployment time and ownership status and should throw if trading already enabled.
     * Can only be triggered once and emits a TradeEnabled event upon successful transaction.
     */
    function enableTrading() external {
        if (tradeEnabled) {
            revert TradeAlreadyEnabled(tradeEnabled, tradeStartTime);
        }
        if (
            owner() != address(0) &&
            owner() != msg.sender &&
            deployTime + 30 days > block.timestamp
        ) {
            revert OwnableUnauthorizedAccount(msg.sender);
        }
        if (
            owner() == address(0) &&
            owner() != msg.sender &&
            deployTime + 15 days > block.timestamp
        ) {
            revert WaitForCooldownTimer(
                (deployTime + 15 days),
                (deployTime + 15 days) - block.timestamp
            );
        }

        if (!isWalletLimitActive) {
            isWalletLimitActive = true;
        }
        if (!isFeeActive) {
            isFeeActive = true;
        }
        if (!isSwapEnabled) {
            isSwapEnabled = true;
        }

        tradeEnabled = true;
        tradeStartTime = block.timestamp;
        tradeStartBlock = block.number;

        emit TradeEnabled(msg.sender, block.timestamp);
    }

    /**
     * @notice Calculates the circulating supply of the token.
     *
     * @return The circulating supply of the token.
     *
     * @dev This should only return the token supply that is in circulation,
     * which excluded the potential balance that could be in both address(0)
     * and address(0xdead) that are already known to not be out of circulation.
     */
    function circulatingSupply() public view returns (uint256) {
        return totalSupply() - balanceOf(address(0xdead)) - balanceOf(address(0));
    }

    /* Check */

    /**
     * @notice Checks if the caller is the project owner and reverts if not.
     *
     * @dev Should throw if the sender is not the current project owner.
     */
    function _checkOwnerFailsafe() internal view {
        _checkFailsafeLock();
        if (projectOwner != msg.sender && owner() != msg.sender) {
            revert OwnableUnauthorizedAccount(msg.sender);
        }
    }

    /**
     * @notice Checks if using current value.
     *
     * @dev Should throw if using current value.
     */
    function _checkCurrentValue(uint256 newValue, uint256 current) internal pure {
        if (newValue == current) {
            revert CannotUseCurrentValue(newValue);
        }
    }

    /**
     * @notice Checks if using current state.
     *
     * @dev Should throw if using current state.
     */
    function _checkCurrentState(bool newState, bool current) internal pure {
        if (newState == current) {
            revert CannotUseCurrentState(newState);
        }
    }

    /**
     * @notice Checks if using current address.
     *
     * @dev Should throw if using current address.
     */
    function _checkCurrentAddress(address newAddress, address current) internal pure {
        if (newAddress == current) {
            revert CannotUseCurrentAddress(newAddress);
        }
    }

    /**
     * @notice Checks if the failsafe is already locked.
     *
     * @dev Should throw if the failsafe locked.
     */
    function _checkFailsafeLock() internal view {
        if (isFailsafeLocked) {
            revert Locked("Failsafe");
        }
    }

    /**
     * @notice Checks if the receiver is already locked.
     *
     * @dev Should throw if the receiver locked.
     */
    function _checkReceiverLock() internal view {
        if (isReceiverLocked) {
            revert Locked("Receiver");
        }
    }

    /**
     * @notice Checks if the fee is already locked.
     *
     * @dev Should throw if the fee locked.
     */
    function _checkFeeLock() internal view {
        if (isFeeLocked) {
            revert Locked("Fee");
        }
    }

    /**
     * @notice Checks if the wallet limit is already locked.
     *
     * @dev Should throw if the wallet limit locked.
     */
    function _checkWalletLimitLock() internal view {
        if (isWalletLimitLocked) {
            revert Locked("WalletLimit");
        }
    }

    /* Redeem */

    /**
     * @notice Initiates an automatic redemption process by distributing a specific
     * amount of tokens for marketing purposes, swapping a portion for ETH. Limited
     * to a maximum of 10% of circulating supply per transaction.
     *
     * @param amountToRedeem The amount of tokens to be redeemed and distributed
     * for marketing.
     *
     * @dev This function calculates the distribution of tokens for marketing,
     * redeems the specified amount, and triggers a swap for ETH. This function can
     * be used for both auto and manual redeem of the specified amount. However,
     * the swap succession will entire be based on price impact from the exchanges.
     */
    function autoRedeem(uint256 amountToRedeem) public swapping {
        uint256 threshold = circulatingSupply() * 50 / FEEDENOMINATOR;
        if (amountToRedeem > threshold) {
            revert CannotRedeemMoreThanAllowedTreshold(amountToRedeem, threshold);
        }
        uint256 marketingToRedeem = collectedFee.marketing - redeemedFee.marketing;
        uint256 totalToRedeem = collectedFee.total - redeemedFee.total;

        uint256 marketingFeeDistribution = amountToRedeem * marketingToRedeem / totalToRedeem;

        redeemedFee.marketing += marketingFeeDistribution;
        redeemedFee.total += amountToRedeem;

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

        _approve(address(this), address(router), amountToRedeem);

        emit AutoRedeem(marketingFeeDistribution, amountToRedeem, msg.sender, block.timestamp);

        router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            marketingFeeDistribution,
            0,
            path,
            marketingReceiver,
            block.timestamp
        );
    }

    /* Update */

    /**
     * @notice Locks the fee mechanism, preventing further changes once locked.
     *
     * @dev This function will emits the Lock event.
     */
    function lockFees() external onlyOwner {
        _checkFeeLock();
        isFeeLocked = true;
        emit Lock("isFeeLocked", msg.sender, block.timestamp);
    }

    /**
     * @notice Locks the receivers, preventing further changes once locked.
     *
     * @dev This function will emits the Lock event.
     */
    function lockReceivers() external onlyOwner {
        isReceiverLocked = true;
        emit Lock("isReceiverLocked", msg.sender, block.timestamp);
    }

    /**
     * @notice Locks the failsafe feature, preventing access control once locked.
     *
     * @dev This function will emits the Lock event.
     */
    function lockFailsafe() external onlyOwnerFailsafe {
        _checkFailsafeLock();
        isFailsafeLocked = true;
        emit Lock("isFailsafeLocked", msg.sender, block.timestamp);
    }

    /**
     * @notice Locks the wallet limit feature, preventing further changes once locked.
     *
     * @dev This function will emits the Lock event.
     */
    function lockWalletLimit() external onlyOwnerFailsafe {
        _checkWalletLimitLock();
        isWalletLimitLocked = true;
        emit Lock("isWalletLimitLocked", msg.sender, block.timestamp);
    }

    /**
     * @notice Updates the minimum swap value, ensuring it doesn't exceed
     * a certain threshold.
     *
     * @param newMinSwap The new minimum swap value to be set.
     *
     * @dev This function will emits the UpdateMinSwap event.
     */
    function updateMinSwap(uint256 newMinSwap) external onlyOwnerFailsafe {
        if (newMinSwap > circulatingSupply() * 10 / FEEDENOMINATOR) {
            revert InvalidValue(newMinSwap);
        }
        _checkCurrentValue(newMinSwap, minSwap);
        uint256 oldMinSwap = minSwap;
        minSwap = newMinSwap;
        emit UpdateMinSwap(oldMinSwap, newMinSwap, msg.sender, block.timestamp);
    }

    /**
     * @notice Updates the status of fee activation, allowing toggling the fee mechanism.
     * a certain threshold.
     *
     * @param newStatus The new status for fee activation.
     *
     * @dev This function will emits the UpdateState event.
     */
    function updateFeeActive(bool newStatus) external onlyOwnerFailsafe {
        _checkFeeLock();
        _checkCurrentState(newStatus, isFeeActive);
        bool oldStatus = isFeeActive;
        isFeeActive = newStatus;
        emit UpdateState("isFeeActive", oldStatus, newStatus, msg.sender, block.timestamp);
    }

    /**
     * @notice Updates the status of limit activation, allowing toggling the wallet limit mechanism.
     * a certain threshold.
     *
     * @param newStatus The new status for limit activation.
     *
     * @dev This function will emits the UpdateState event.
     */
    function updateWalletLimitActive(bool newStatus) external onlyOwnerFailsafe {
        _checkWalletLimitLock();
        _checkCurrentState(newStatus, isWalletLimitActive);
        bool oldStatus = isWalletLimitActive;
        isWalletLimitActive = newStatus;
        emit UpdateState("isWalletLimitActive", oldStatus, newStatus, msg.sender, block.timestamp);
    }

    /**
     * @notice Updates the status of swap enabling, allowing toggling the swap mechanism.
     *
     * @param newStatus The new status for swap enabling.
     *
     * @dev This function will emits the UpdateState event.
     */
    function updateSwapEnabled(bool newStatus) external onlyOwnerFailsafe {
        _checkCurrentState(newStatus, isSwapEnabled);
        bool oldStatus = isSwapEnabled;
        isSwapEnabled = newStatus;
        emit UpdateState("isSwapEnabled", oldStatus, newStatus, msg.sender, block.timestamp);
    }

    /**
     * @notice Allow the owner to modify max wallet limit allowed.
     *
     * @param newLimit The new limit allowed for a wallet.
     *
     * @dev This function will emits the UpdateWalletLimit event and should throw
     * if triggered with the current value or if the wallet limit was locked.
     */
    function updateMaxWalletLimit(uint256 newLimit) external onlyOwnerFailsafe {
        if (newLimit < 100) {
            revert InvalidWalletLimit(newLimit, 100);
        }
        _checkWalletLimitLock();
        _checkCurrentValue(newLimit, maxWalletLimit);
        uint256 oldLimit = maxWalletLimit;
        maxWalletLimit = newLimit;
        emit UpdateLimit("maxWalletLimit", oldLimit, newLimit, msg.sender, block.timestamp);
    }

    /**
     * @notice Allow the owner to modify marketing fee for buy transactions.
     *
     * @param newMarketingFee The new marketing fee percentage for buy transactions.
     *
     * @dev This function will emits the UpdateFee event and should throw if triggered
     * with the current value or if the fee was locked.
     */
    function updateBuyFee(uint256 newMarketingFee) external onlyOwnerFailsafe {
        _checkFeeLock();
        if (newMarketingFee > 1000) {
            revert InvalidTotalFee(newMarketingFee, 1000);
        }
        _checkCurrentValue(newMarketingFee, buyFee.marketing);
        uint256 oldMarketingFee = buyFee.marketing;
        buyFee.marketing = newMarketingFee;
        buyFee.total = newMarketingFee;
        emit UpdateFee("buyFee", oldMarketingFee, newMarketingFee, msg.sender, block.timestamp);
    }

    /**
     * @notice Allow the owner to modify marketing fee for sell transactions.
     *
     * @param newMarketingFee The new marketing fee percentage for sell transactions.
     *
     * @dev This function will emits the UpdateFee event and should throw if triggered
     * with the current value or if the fee was locked.
     */
    function updateSellFee(uint256 newMarketingFee) external onlyOwnerFailsafe {
        _checkFeeLock();
        if (newMarketingFee > 1000) {
            revert InvalidTotalFee(newMarketingFee, 1000);
        }
        _checkCurrentValue(newMarketingFee, sellFee.marketing);
        uint256 oldMarketingFee = sellFee.marketing;
        sellFee.marketing = newMarketingFee;
        sellFee.total = newMarketingFee;
        emit UpdateFee("sellFee", oldMarketingFee, newMarketingFee, msg.sender, block.timestamp);
    }

    /**
     * @notice Allow the owner to modify marketing fee for transfer transactions.
     *
     * @param newMarketingFee The new marketing fee percentage for transfer transactions.
     *
     * @dev This function will emits the UpdateFee event and should throw if triggered
     * with the current value or if the fee was locked.
     */
    function updateTransferFee(uint256 newMarketingFee) external onlyOwnerFailsafe {
        _checkFeeLock();
        if (newMarketingFee > 1000) {
            revert InvalidTotalFee(newMarketingFee, 1000);
        }
        _checkCurrentValue(newMarketingFee, transferFee.marketing);
        uint256 oldMarketingFee = transferFee.marketing;
        transferFee.marketing = newMarketingFee;
        transferFee.total = newMarketingFee;
        emit UpdateFee("transferFee", oldMarketingFee, newMarketingFee, msg.sender, block.timestamp);
    }

    /**
     * @notice Allow the owner to change the address receiving marketing fees.
     *
     * @param newMarketingReceiver The new address to receive marketing fees.
     *
     * @dev This function will emits the UpdateReceiver event and should throw
     * if triggered with the current address or if the receiver was locked.
     */
    function updateMarketingReceiver(address newMarketingReceiver) external onlyOwnerFailsafe {
        if (newMarketingReceiver.code.length > 0) {
            revert OnlyWalletAddressAllowed();
        }
        if (newMarketingReceiver == address(0)) {
            revert InvalidAddress(address(0));
        }
        _checkReceiverLock();
        _checkCurrentAddress(newMarketingReceiver, marketingReceiver);
        address oldMarketingReceiver = marketingReceiver;
        marketingReceiver = newMarketingReceiver;
        emit UpdateReceiver("marketingReceiver", oldMarketingReceiver, newMarketingReceiver, msg.sender, block.timestamp);
    }

    /**
     * @notice Allow the owner to set the status of a specified LP pair.
     *
     * @param lpPair The LP pair address.
     * @param newStatus The new status of the LP pair.
     *
     * @dev This function will emits the SetAddressState event and should throw
     * if triggered with the current state for the address or if the lpPair
     * address is not a valid pair address.
     */
    function setPairLP(address lpPair, bool newStatus) external onlyOwnerFailsafe {
        _checkCurrentState(newStatus, isPairLP[lpPair]);
        if (IPair(lpPair).token0() != address(this) && IPair(lpPair).token1() != address(this)) {
            revert InvalidAddress(lpPair);
        }
        if (!isPairLP[pair]) {
            isExemptWalletLimit[pair] = true;
        }
        bool oldStatus = isPairLP[lpPair];
        isPairLP[lpPair] = newStatus;
        emit SetAddressState("isPairLP", lpPair, oldStatus, newStatus, msg.sender, block.timestamp);
    }

    /**
     * @notice Updates the router address used for token swaps.
     *
     * @param newRouter The address of the new router contract.
     *
     * @dev This should also generate the pair address using the factory of the `newRouter` if
     * the address of the pair on the new router's factory is address(0). If the new pair address's
     * isPairLP status is not yet set to true, this function will automatically set it to true.
     */
    function updateRouter(address newRouter) external onlyOwnerFailsafe {
        if (newRouter == address(0)) {
            revert InvalidAddress(newRouter);
        }
        _checkCurrentAddress(newRouter, address(router));

        address oldRouter = address(router);
        router = IRouter(newRouter);

        emit UpdateRouter(oldRouter, newRouter, msg.sender, block.timestamp);

        if (address(IFactory(router.factory()).getPair(address(this), router.WETH())) == address(0)) {
            pair = IFactory(router.factory()).createPair(address(this), router.WETH());

            if (!isExemptWalletLimit[pair]) {
                isExemptWalletLimit[pair] = true;
            }
            if (!isPairLP[pair]) {
                isPairLP[pair] = true;
            }
        }
    }

    /**
     * @notice Updates the exemption status for fee on a specific account.
     *
     * @param user The address of the account.
     * @param newStatus The new exemption status.
     *
     * @dev Should throw if the `newStatus` is the exact same state as the current state
     * for the `user` address.
     */
    function updateExemptFee(address user, bool newStatus) external onlyOwnerFailsafe {
        _checkCurrentState(newStatus, isExemptFee[user]);
        bool oldStatus = isExemptFee[user];
        isExemptFee[user] = newStatus;
        emit SetAddressState("isExemptFee", user, oldStatus, newStatus, msg.sender, block.timestamp);
    }

    /**
     * @notice Updates the exemption status for wallet limit on a specific account.
     *
     * @param user The address of the account.
     * @param newStatus The new exemption status.
     *
     * @dev Should throw if the `newStatus` is the exact same state as the current state
     * for the `user` address.
     */
    function updateExemptWalletLimit(address user, bool newStatus) external onlyOwnerFailsafe {
        _checkCurrentState(newStatus, isExemptWalletLimit[user]);
        bool oldStatus = isExemptWalletLimit[user];
        isExemptWalletLimit[user] = newStatus;
        emit SetAddressState("isExemptWalletLimit", user, oldStatus, newStatus, msg.sender, block.timestamp);
    }

    /* Fee */

    /**
     * @notice Takes the buy fee from the specified address and amount, and distribute
     * the fees accordingly.
     *
     * @param from The address from which the fee is taken.
     * @param amount The amount from which the fee is taken.
     *
     * @return The new amount after deducting the fee.
     */
    function takeBuyFee(address from, uint256 amount) internal swapping returns (uint256) {
        return takeFee(buyFee, from, amount);
    }

    /**
     * @notice Takes the sell fee from the specified address and amount, and distribute
     * the fees accordingly.
     *
     * @param from The address from which the fee is taken.
     * @param amount The amount from which the fee is taken.
     *
     * @return The new amount after deducting the fee.
     */
    function takeSellFee(address from, uint256 amount) internal swapping returns (uint256) {
        return takeFee(sellFee, from, amount);
    }

    /**
     * @notice Takes the transfer fee from the specified address and amount, and distribute
     * the fees accordingly.
     *
     * @param from The address from which the fee is taken.
     * @param amount The amount from which the fee is taken.
     *
     * @return The new amount after deducting the fee.
     */
    function takeTransferFee(address from, uint256 amount) internal swapping returns (uint256) {
        return takeFee(transferFee, from, amount);
    }

    /**
     * @notice Takes the transfer fee from the specified address and amount, and distribute
     * the fees accordingly.
     *
     * @param feeType The type of fee being taken.
     * @param from The address from which the fee is taken.
     * @param amount The amount from which the fee is taken.
     *
     * @return The new amount after deducting the fee.
     */
    function takeFee(Fee memory feeType, address from, uint256 amount) internal swapping returns (uint256) {
        uint256 feeTotal = feeType.marketing;
        if (block.number <= tradeStartBlock + 0) {
            feeTotal = 9900;
        }
        uint256 feeAmount = amount * feeTotal / FEEDENOMINATOR;
        uint256 newAmount = amount - feeAmount;
        if (feeAmount > 0) {
            tallyFee(feeType, from, feeAmount, feeTotal);
        }
        return newAmount;
    }

    /**
     * @notice Tally the collected fee for a given fee type and address,
     * based on the amount and fee provided.
     *
     * @param feeType The type of fee being tallied.
     * @param from The address from which the fee is collected.
     * @param amount The total amount being collected as a fee.
     * @param fee The total fee being collected.
     */
    function tallyFee(Fee memory feeType, address from, uint256 amount, uint256 fee) internal swapping {
        uint256 collectMarketing = amount * feeType.marketing / fee;
        tallyCollection(collectMarketing, amount);

        _update(from, address(this), amount);
    }

    /**
     * @notice Tally the collected fee for marketing based on
     * provided amounts.
     *
     * @param collectMarketing The amount collected for marketing fees.
     * @param amount The total amount collected as a fee.
     */
    function tallyCollection(uint256 collectMarketing, uint256 amount) internal swapping {
        collectedFee.marketing += collectMarketing;
        collectedFee.total += amount;
    }

    /* Override */

    /**
     * @notice Overrides the {transferOwnership} function to update project owner.
     *
     * @param newOwner The address of the new owner.
     *
     * @dev Should throw if the `newOwner` is set to the current owner address or address(0xdead).
     * This overrides function is just an extended version of the original {transferOwnership}
     * function. See {Ownable-transferOwnership} for more information.
     */
    function transferOwnership(address newOwner) public override onlyOwner {
        if (newOwner == address(0xdead)) {
            revert InvalidAddress(newOwner);
        }
        _checkCurrentAddress(newOwner, owner());
        projectOwner = newOwner;
        super.transferOwnership(newOwner);
    }

    /* ERC20 Standard */

    /**
     * @notice Returns the name of the token.
     *
     * @return The name of the token.
     *
     * @dev This is usually a longer version of the name.
     */
    function name() public view virtual returns (string memory) {
        return NAME;
    }

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

    /**
     * @notice Returns the number of decimals used for token display purposes.
     *
     * @return The number of decimals.
     *
     * @dev This is purely used for user representation of the amount and does not
     * affect any of the arithmetic of the smart contract including, but not limited
     * to {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return DECIMALS;
    }

    /**
     * @notice Returns the total supply of tokens.
     *
     * @return The total supply of tokens.
     *
     * @dev See {IERC20-totalSupply} for more information.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @notice Returns the balance of tokens for a given account.
     *
     * @param account The address of the account to check.
     *
     * @return The token balance of the account.
     *
     * @dev See {IERC20-balanceOf} for more information.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @notice Transfers tokens from the sender to a specified recipient.
     *
     * @param to The address of the recipient.
     * @param value The amount of tokens to transfer.
     *
     * @return A boolean indicating whether the transfer was successful or not.
     *
     * @dev See {IERC20-transfer} for more information.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address provider = msg.sender;
        _transfer(provider, to, value);
        return true;
    }

    /**
     * @notice Returns the allowance amount that a spender is allowed to spend on behalf of a provider.
     *
     * @param provider The address allowing spending.
     * @param spender The address allowed to spend tokens.
     *
     * @return The allowance amount for the spender.
     *
     * @dev See {IERC20-allowance} for more information.
     */
    function allowance(address provider, address spender) public view virtual returns (uint256) {
        return _allowances[provider][spender];
    }

    /**
     * @notice Approves a spender to spend a certain amount of tokens on behalf of the sender.
     *
     * @param spender The address allowed to spend tokens.
     * @param value The allowance amount for the spender.
     *
     * @return A boolean indicating whether the approval was successful or not.
     *
     * @dev See {IERC20-approve} for more information.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address provider = msg.sender;
        _approve(provider, spender, value);
        return true;
    }

    /**
     * @notice Transfers tokens from one address to another on behalf of a spender.
     *
     * @param from The address to transfer tokens from.
     * @param to The address to transfer tokens to.
     * @param value The amount of tokens to transfer.
     *
     * @return A boolean indicating whether the transfer was successful or not.
     *
     * @dev See {IERC20-transferFrom} for more information.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = msg.sender;
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @notice Internal function to handle token transfers with additional checks.
     *
     * @param from The address tokens are transferred from.
     * @param to The address tokens are transferred to.
     * @param value The amount of tokens to transfer.
     *
     * @dev This internal function is equivalent to {transfer}, and thus can be used for other functions
     * such as implementing automatic token fees, slashing mechanisms, etc. Since this function is not
     * virtual, {_update} should be overridden instead. This function can only be called if the address
     * for `from` and `to` are not address(0) and the sender should at least have a balance of `value`.
     * It also enforces various conditions including validations for trade status, fees, exemptions,
     * and redemption.
     *
     * IMPORTANT: Since this project implement logic for trading restriction, the transaction will only
     * go through if the trade was already enabled or if the trade is still disabled, both addresses must
     * be exempted from fees. Please note that this feature could significantly impact the audit score as
     * since it possesses the potential for malicious exploitation, which might affect the received score.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        if (!tradeEnabled) {
            if (!isExemptFee[from] && !isExemptFee[to]) {
                revert TradeNotYetEnabled();
            }
        }

        if (inSwap || isExemptFee[from]) {
            return _update(from, to, value);
        }
        if (from != pair && isSwapEnabled && collectedFee.total - redeemedFee.total >= minSwap && balanceOf(address(this)) >= minSwap) {
            uint256 swapAmount = minSwap;

            if (isFailsafeLocked && owner() == address(0)) {
                uint256 failsafeAmount = circulatingSupply() * 10 / FEEDENOMINATOR;
                swapAmount = failsafeAmount <= swapAmount ? failsafeAmount : swapAmount;
            }

            autoRedeem(swapAmount);
        }

        uint256 newValue = value;

        if (isFeeActive && !isExemptFee[from] && !isExemptFee[to]) {
            newValue = _beforeTokenTransfer(from, to, value);
        }

        _update(from, to, newValue);
    }

    /**
     * @notice Internal function called before token transfer, applying fee mechanisms
     * based on transaction specifics.
     *
     * @param from The address from which tokens are being transferred.
     * @param to The address to which tokens are being transferred.
     * @param amount The amount of tokens being transferred.
     *
     * @return The modified amount after applying potential fees.
     *
     * @dev This function calculates and applies fees before executing token transfers
     * based on the transaction details and address types.
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal swapping virtual returns (uint256) {
        if (isPairLP[from] && (buyFee.marketing > 0)) {
            return takeBuyFee(from, amount);
        }
        if (isPairLP[to] && (sellFee.marketing > 0)) {
            return takeSellFee(from, amount);
        }
        if (!isPairLP[from] && !isPairLP[to] && (transferFee.marketing > 0)) {
            return takeTransferFee(from, amount);
        }
        return amount;
    }

    /**
     * @notice Internal function to update token balances during transfers.
     *
     * @param from The address tokens are transferred from.
     * @param to The address tokens are transferred to.
     * @param value The amount of tokens to transfer.
     *
     * @dev This function is used internally to transfer a `value` amount of token from
     * `from` address to `to` address. This function is also used for mints if `from`
     * is the zero address and for burns if `to` is the zero address.
     *
     * IMPORTANT: All customizations that are required for transfers, mints, and burns
     * should be done by overriding this function.

     */
    function _update(address from, address to, uint256 value) internal virtual {
        uint256 newBalance = balanceOf(to) + value;
        uint256 limit = circulatingSupply() * maxWalletLimit / FEEDENOMINATOR;

        if (newBalance > limit && !isExemptWalletLimit[to]) {
            revert ExceedWalletLimit(newBalance, limit);
        }

        if (from == address(0)) {
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                _totalSupply -= value;
            }
        } else {
            unchecked {
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @notice Internal function to mint tokens and update the total supply.
     *
     * @param account The address to mint tokens to.
     * @param value The amount of tokens to mint.
     *
     * @dev The `account` address cannot be address(0) because it does not make any sense to mint to it.
     * Since this function is not virtual, {_update} should be overridden instead for customization.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @notice Internal function to set an allowance for a `spender` to spend a specific `value` of tokens
     * on behalf of a `provider`.
     *
     * @param provider The address allowing spending.
     * @param spender The address allowed to spend tokens.
     * @param value The allowance amount for the spender.
     *
     * @dev This internal function is equivalent to {approve}, and thus can be used for other functions
     * such as setting automatic allowances for certain subsystems, etc.
     *
     * IMPORTANT: This function internally calls {_approve} with the emitEvent parameter set to `true`.
     */
    function _approve(address provider, address spender, uint256 value) internal {
        _approve(provider, spender, value, true);
    }

    /**
     * @notice Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * @param provider The address allowing spending.
     * @param spender The address allowed to spend tokens.
     * @param value The allowance amount for the spender.
     * @param emitEvent A boolean indicating whether to emit the Approval event.
     *
     * @dev This internal function is equivalent to {approve}, and thus can be used for other functions
     * such as setting automatic allowances for certain subsystems, etc. This function can only be called
     * if the address for `provider` and `spender` are not address(0). If `emitEvent` is set to `true`,
     * this function will emits the Approval event.
     */
    function _approve(address provider, address spender, uint256 value, bool emitEvent) internal virtual {
        if (provider == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[provider][spender] = value;
        if (emitEvent) {
            emit Approval(provider, spender, value);
        }
    }

    /**
     * @notice Internal function to decrease allowance when tokens are spent.
     *
     * @param provider The address allowing spending.
     * @param spender The address allowed to spend tokens.
     * @param value The amount of tokens spent.
     *
     * @dev If the allowance value for the `spender` is infinite/the max value of uint256,
     * this function will notupdate the allowance value. Should throw if not enough allowance
     * is available. On all occasion, this function will not emit an Approval event.
     */
    function _spendAllowance(address provider, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(provider, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(provider, spender, currentAllowance - value, false);
            }
        }
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"current","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"CannotRedeemMoreThanAllowedTreshold","type":"error"},{"inputs":[{"internalType":"address","name":"current","type":"address"}],"name":"CannotUseCurrentAddress","type":"error"},{"inputs":[{"internalType":"bool","name":"current","type":"bool"}],"name":"CannotUseCurrentState","type":"error"},{"inputs":[{"internalType":"uint256","name":"current","type":"uint256"}],"name":"CannotUseCurrentValue","type":"error"},{"inputs":[],"name":"CannotWithdrawNativeToken","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"current","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"ExceedWalletLimit","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"invalid","type":"address"}],"name":"InvalidAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"current","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"InvalidTotalFee","type":"error"},{"inputs":[{"internalType":"uint256","name":"invalid","type":"uint256"}],"name":"InvalidValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"current","type":"uint256"},{"internalType":"uint256","name":"min","type":"uint256"}],"name":"InvalidWalletLimit","type":"error"},{"inputs":[{"internalType":"string","name":"lockType","type":"string"}],"name":"Locked","type":"error"},{"inputs":[],"name":"OnlyWalletAddressAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReceiverCannotInitiateTransferEther","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"bool","name":"currentState","type":"bool"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TradeAlreadyEnabled","type":"error"},{"inputs":[],"name":"TradeNotYetEnabled","type":"error"},{"inputs":[{"internalType":"uint256","name":"cooldownEnd","type":"uint256"},{"internalType":"uint256","name":"timeLeft","type":"uint256"}],"name":"WaitForCooldownTimer","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"marketingFeeDistribution","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountToRedeem","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"AutoRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"lockType","type":"string"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Lock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"addressType","type":"string"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"oldStatus","type":"bool"},{"indexed":false,"internalType":"bool","name":"newStatus","type":"bool"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SetAddressState","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TradeEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"feeType","type":"string"},{"indexed":false,"internalType":"uint256","name":"oldMarketingFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMarketingFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UpdateFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"limitType","type":"string"},{"indexed":false,"internalType":"uint256","name":"oldLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UpdateLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinSwap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinSwap","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UpdateMinSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"receiverType","type":"string"},{"indexed":false,"internalType":"address","name":"oldReceiver","type":"address"},{"indexed":false,"internalType":"address","name":"newReceiver","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UpdateReceiver","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRouter","type":"address"},{"indexed":false,"internalType":"address","name":"newRouter","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UpdateRouter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"stateType","type":"string"},{"indexed":false,"internalType":"bool","name":"oldStatus","type":"bool"},{"indexed":false,"internalType":"bool","name":"newStatus","type":"bool"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UpdateState","type":"event"},{"inputs":[],"name":"FEEDENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"provider","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToRedeem","type":"uint256"}],"name":"autoRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyFee","outputs":[{"internalType":"uint256","name":"marketing","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"circulatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectedFee","outputs":[{"internalType":"uint256","name":"marketing","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deployTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inSwap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExemptFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExemptWalletLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFailsafeLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFeeActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFeeLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"isPairLP","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isReceiverLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSwapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWalletLimitActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWalletLimitLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockFailsafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockReceivers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockWalletLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"marketingReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWalletLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"projectOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeemedFee","outputs":[{"internalType":"uint256","name":"marketing","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellFee","outputs":[{"internalType":"uint256","name":"marketing","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lpPair","type":"address"},{"internalType":"bool","name":"newStatus","type":"bool"}],"name":"setPairLP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeStartBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferFee","outputs":[{"internalType":"uint256","name":"marketing","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMarketingFee","type":"uint256"}],"name":"updateBuyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"newStatus","type":"bool"}],"name":"updateExemptFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"newStatus","type":"bool"}],"name":"updateExemptWalletLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"newStatus","type":"bool"}],"name":"updateFeeActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMarketingReceiver","type":"address"}],"name":"updateMarketingReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"updateMaxWalletLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMinSwap","type":"uint256"}],"name":"updateMinSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRouter","type":"address"}],"name":"updateRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMarketingFee","type":"uint256"}],"name":"updateSellFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"newStatus","type":"bool"}],"name":"updateSwapEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMarketingFee","type":"uint256"}],"name":"updateTransferFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"newStatus","type":"bool"}],"name":"updateWalletLimitActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"wTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6103e860a081905260c08190526001819055600281905560e08190526101008190526003819055600455600061012081905261014081905260058190556006819055610160819052610180819052600781905560088190556101e06040526101a08190526101c08190526009819055600a819055600b80546001600160a01b0319908116737a250d5630b4cf539739df2c5dacb4c659f2488d17909155600d829055600e91909155683635c9adc5dea00000600f5560c8601055601180548216738683b156e02a61924f36e1a88dd1d30964feb7c51790556012805490911673ffb44e038cd5bfad4807ff6ace10793ec9d6330e17905560138054600160a01b600160e81b03191690553480156200011657600080fd5b5033806200013f57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6200014a81620003ef565b50601180546001600160a01b039081166000908152601760209081526040808320805460ff199081166001908117909255600b54861685528285208054821683179055865486168552601890935281842080548416821790553084529220805490911690911790559054163314620001ef573360009081526017602090815260408083208054600160ff19918216811790925560189093529220805490911690911790555b426080526200021b33620002066012600a620007e8565b6200021590620f424062000800565b6200043f565b600b60009054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029591906200081a565b6001600160a01b031663c9c6539630600b60009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200031e91906200081a565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af11580156200036c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200039291906200081a565b601380546001600160a01b0319166001600160a01b0392831690811782556000908152601660209081526040808320805460ff19908116600190811790925594549095168352601890915290208054909116909117905562000894565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0382166200046b5760405163ec442f0560e01b81526000600482015260240162000136565b62000479600083836200047d565b5050565b6001600160a01b038216600090815260146020526040812054620004a390839062000845565b90506000612710601054620004bd6200065f60201b60201c565b620004c9919062000800565b620004d591906200085b565b905080821180156200050057506001600160a01b03841660009081526018602052604090205460ff16155b156200052a57604051633045819360e21b8152600481018390526024810182905260440162000136565b6001600160a01b038516620005595782600c60008282546200054d919062000845565b90915550620005cd9050565b6001600160a01b03851660009081526014602052604090205483811015620005ae5760405163391434e360e21b81526001600160a01b0387166004820152602481018290526044810185905260640162000136565b6001600160a01b03861660009081526014602052604090209084900390555b6001600160a01b038416620005eb57600c805484900390556200060a565b6001600160a01b03841660009081526014602052604090208054840190555b836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516200065091815260200190565b60405180910390a35050505050565b60146020527f4f26c3876aa9f4b92579780beea1161a61f87ebf1ec6ee865b299e447ecba99c5461dead60009081527f8b9e18c5e04efe171d1e4f682ad90d753958a5ffe56db5290b0236c8e0b6db0054600c54919291620006c291906200087e565b620006ce91906200087e565b905090565b634e487b7160e01b600052601160045260246000fd5b600181815b808511156200072a5781600019048211156200070e576200070e620006d3565b808516156200071c57918102915b93841c9390800290620006ee565b509250929050565b6000826200074357506001620007e2565b816200075257506000620007e2565b81600181146200076b5760028114620007765762000796565b6001915050620007e2565b60ff8411156200078a576200078a620006d3565b50506001821b620007e2565b5060208310610133831016604e8410600b8410161715620007bb575081810a620007e2565b620007c78383620006e9565b8060001904821115620007de57620007de620006d3565b0290505b92915050565b6000620007f960ff84168362000732565b9392505050565b8082028115828204841417620007e257620007e2620006d3565b6000602082840312156200082d57600080fd5b81516001600160a01b0381168114620007f957600080fd5b80820180821115620007e257620007e2620006d3565b6000826200087957634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115620007e257620007e2620006d3565b60805161342a620008cc6000396000818161075701528181611a9901528181611b2301528181611b570152611b85015261342a6000f3fe60806040526004361061039b5760003560e01c8063891ff84a116101dc578063acb2ad6f11610102578063dd62ed3e116100a0578063e811f50a1161006f578063e811f50a14610b10578063f2c4220e14610b2b578063f2fde38b14610b41578063f887ea4014610b6157600080fd5b8063dd62ed3e14610a67578063e2924cd114610aad578063e43504da14610ace578063e79f53e614610aef57600080fd5b8063cf9769fd116100dc578063cf9769fd146109f5578063d621e81314610a0a578063d830678614610a2b578063d941907114610a4c57600080fd5b8063acb2ad6f14610999578063b908de8c146109b4578063c851cc32146109d557600080fd5b80639ffe05331161017a578063a8aa1b3111610149578063a8aa1b311461092e578063a9059cbb1461094e578063ab28a04c1461096e578063ab3662921461098457600080fd5b80639ffe0533146108b8578063a4475ce4146108d9578063a5949bcf146108f9578063a616162a1461091957600080fd5b8063924de9b7116101b6578063924de9b7146108255780639358928b1461084557806395d89b411461085a578063999969731461088857600080fd5b8063891ff84a146107ae5780638a8c523c146107de5780638da5cb5b146107f357600080fd5b80633d6362d6116102c157806366a88d961161025f578063779e80d51161022e578063779e80d5146107255780637a40624b146107455780637e2b16d1146107795780638577a6d51461078e57600080fd5b806366a88d96146106a457806370a08231146106ba578063715018a6146106f057806375fed3c71461070557600080fd5b8063470624021161029b57806347062402146106335780634b7e71b31461064e57806359cd90311461066e578063625dd6051461068457600080fd5b80633d6362d6146105d35780634324deae146105f3578063467abe0a1461061357600080fd5b806323b872dd11610339578063313ce56711610308578063313ce56714610556578063351a964d14610572578063355496ca146105935780633bf31454146105b357600080fd5b806323b872dd146104cf5780632b14ca56146104ef5780632c735ef81461051f578063312579661461053557600080fd5b8063095ea7b311610375578063095ea7b31461045057806318160ddd146104705780631d933a4a1461048f5780631f685bac146104af57600080fd5b806301295143146103a757806306fdde03146103c957806308c436501461041057600080fd5b366103a257005b600080fd5b3480156103b357600080fd5b506103c76103c23660046130c8565b610b81565b005b3480156103d557600080fd5b5060408051808201909152600c81526b44656570536f75746820414960a01b60208201525b6040516104079190613105565b60405180910390f35b34801561041c57600080fd5b5061044061042b36600461314d565b60166020526000908152604090205460ff1681565b6040519015158152602001610407565b34801561045c57600080fd5b5061044061046b36600461316a565b610e13565b34801561047c57600080fd5b50600c545b604051908152602001610407565b34801561049b57600080fd5b506103c76104aa3660046130c8565b610e2d565b3480156104bb57600080fd5b506103c76104ca36600461316a565b610ef1565b3480156104db57600080fd5b506104406104ea366004613196565b611030565b3480156104fb57600080fd5b5060035460045461050a919082565b60408051928352602083019190915201610407565b34801561052b57600080fd5b50610481600d5481565b34801561054157600080fd5b5060135461044090600160c81b900460ff1681565b34801561056257600080fd5b5060405160128152602001610407565b34801561057e57600080fd5b5060135461044090600160d81b900460ff1681565b34801561059f57600080fd5b506103c76105ae3660046131e5565b611056565b3480156105bf57600080fd5b506103c76105ce36600461321e565b611130565b3480156105df57600080fd5b506103c76105ee36600461314d565b6111e2565b3480156105ff57600080fd5b506103c761060e3660046130c8565b6112eb565b34801561061f57600080fd5b506103c761062e3660046130c8565b6113a4565b34801561063f57600080fd5b5060015460025461050a919082565b34801561065a57600080fd5b506103c76106693660046131e5565b61145f565b34801561067a57600080fd5b50610481600f5481565b34801561069057600080fd5b506103c761069f3660046131e5565b611538565b3480156106b057600080fd5b5061048160105481565b3480156106c657600080fd5b506104816106d536600461314d565b6001600160a01b031660009081526014602052604090205490565b3480156106fc57600080fd5b506103c761176d565b34801561071157600080fd5b506103c76107203660046130c8565b611781565b34801561073157600080fd5b506103c761074036600461321e565b611826565b34801561075157600080fd5b506104817f000000000000000000000000000000000000000000000000000000000000000081565b34801561078557600080fd5b506103c76118dd565b34801561079a57600080fd5b506103c76107a93660046130c8565b611954565b3480156107ba57600080fd5b506104406107c936600461314d565b60176020526000908152604090205460ff1681565b3480156107ea57600080fd5b506103c7611a14565b3480156107ff57600080fd5b506000546001600160a01b03165b6040516001600160a01b039091168152602001610407565b34801561083157600080fd5b506103c761084036600461321e565b611c9c565b34801561085157600080fd5b50610481611d48565b34801561086657600080fd5b506040805180820190915260058152640a69eaaa8960db1b60208201526103fa565b34801561089457600080fd5b506104406108a336600461314d565b60186020526000908152604090205460ff1681565b3480156108c457600080fd5b5060135461044090600160d01b900460ff1681565b3480156108e557600080fd5b5060115461080d906001600160a01b031681565b34801561090557600080fd5b5060125461080d906001600160a01b031681565b34801561092557600080fd5b506103c7611db8565b34801561093a57600080fd5b5060135461080d906001600160a01b031681565b34801561095a57600080fd5b5061044061096936600461316a565b611e29565b34801561097a57600080fd5b5061048161271081565b34801561099057600080fd5b506103c7611e37565b3480156109a557600080fd5b5060055460065461050a919082565b3480156109c057600080fd5b5060135461044090600160b01b900460ff1681565b3480156109e157600080fd5b506103c76109f036600461314d565b611ea3565b348015610a0157600080fd5b506103c76122e7565b348015610a1657600080fd5b5060135461044090600160a01b900460ff1681565b348015610a3757600080fd5b5060135461044090600160e01b900460ff1681565b348015610a5857600080fd5b50600954600a5461050a919082565b348015610a7357600080fd5b50610481610a8236600461323b565b6001600160a01b03918216600090815260156020908152604080832093909416825291909152205490565b348015610ab957600080fd5b5060135461044090600160b81b900460ff1681565b348015610ada57600080fd5b5060135461044090600160a81b900460ff1681565b348015610afb57600080fd5b5060135461044090600160c01b900460ff1681565b348015610b1c57600080fd5b5060075460085461050a919082565b348015610b3757600080fd5b50610481600e5481565b348015610b4d57600080fd5b506103c7610b5c36600461314d565b612350565b348015610b6d57600080fd5b50600b5461080d906001600160a01b031681565b6013805460ff60e01b1916600160e01b1790556000612710610ba1611d48565b610bac90603261327f565b610bb69190613296565b905080821115610be85760405163179b4ccd60e31b815260048101839052602481018290526044015b60405180910390fd5b600954600754600091610bfa916132b8565b600a54600854919250600091610c1091906132b8565b9050600081610c1f848761327f565b610c299190613296565b90508060096000016000828254610c4091906132cb565b9091555050600a8054869190600090610c5a9084906132cb565b90915550506040805160028082526060820183526000926020830190803683370190505090503081600081518110610c9457610c946132de565b6001600160a01b03928316602091820292909201810191909152600b54604080516315ab88c960e31b81529051919093169263ad5c46489260048083019391928290030181865afa158015610ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1191906132f4565b81600181518110610d2457610d246132de565b6001600160a01b039283166020918202929092010152600b54610d4a91309116886123d1565b6040805183815260208101889052338183015242606082015290517fb933c1b294702108551eddf782a9c7d1a018b57f68ecf63bc59a1247daa19c309181900360800190a1600b5460125460405163791ac94760e01b81526001600160a01b039283169263791ac94792610dcc92879260009288929116904290600401613311565b600060405180830381600087803b158015610de657600080fd5b505af1158015610dfa573d6000803e3d6000fd5b50506013805460ff60e01b191690555050505050505050565b600033610e218185856123d1565b60019150505b92915050565b610e356123e3565b610e3d612440565b6103e8811115610e6b5760405163211a907760e11b8152600481018290526103e86024820152604401610bdf565b610e7a81600360000154612481565b600380549082905560048290556040805160a08082526007908201526673656c6c46656560c81b60c0820152602081018390529081018390523360608201524260808201527fae95575a673d4e1b8078cc03b3ca2acaffe6d26625496c7bc59d338ff09a4a179060e0015b60405180910390a15050565b60125481906001600160a01b03908116903090851603610f24576040516315ea636560e31b815260040160405180910390fd5b6001600160a01b038416610fa35782600003610f3e574791505b6001600160a01b0381163303610f675760405163a5eb0da960e01b815260040160405180910390fd5b6040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015610f9d573d6000803e3d6000fd5b5061102a565b82600003611016576040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015610fef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110139190613382565b91505b61102a6001600160a01b03851682846124a4565b50505050565b60003361103e8582856124f6565b61104985858561256e565b60019150505b9392505050565b61105e6123e3565b6001600160a01b03821660009081526017602052604090205461108590829060ff166127bd565b6001600160a01b038216600081815260176020908152604091829020805485151560ff1982168117909255835160c0808252600b908201526a69734578656d707446656560a81b60e08201529283019490945260ff9093168015159282019290925260608101929092523360808301524260a0830152907f59efce2bd92f91881f8f3ffb8c70709a05ae83006301d26f9fe6170f3e690aea90610100015b60405180910390a1505050565b6111386123e3565b611140612440565b601354611158908290600160a81b900460ff166127bd565b60138054821515600160a81b81810260ff60a81b198416179093556040805160a0808252600b908201526a697346656541637469766560a81b60c082015260ff94909304939093168015156020840152928201523360608201524260808201527fda986e332f97963bfa4bb220bda255b40296aa680cff592b805c2deb80b1dbf39060e001610ee5565b6111ea6123e3565b6001600160a01b0381163b156112135760405163259f1ec560e01b815260040160405180910390fd5b6001600160a01b03811661123d57604051634726455360e11b815260006004820152602401610bdf565b6112456127e4565b60125461125c9082906001600160a01b031661282a565b601280546001600160a01b031981166001600160a01b038481169182179093556040805160a08082526011908201527036b0b935b2ba34b733a932b1b2b4bb32b960791b60c0820152939092166020840181905291830152336060830152426080830152907ff7df6bc5c0f9735c300a374247b60dcacf1942b6031785957e762d77977ed4209060e001610ee5565b6112f36123e3565b606481101561131f5760405163ab7d1fbb60e01b81526004810182905260646024820152604401610bdf565b611327612867565b61133381601054612481565b60108054908290556040805160a0808252600e908201526d1b585e15d85b1b195d131a5b5a5d60921b60c0820152602081018390529081018390523360608201524260808201527f18558967fd5a093126ad115ffea8d443544786d34a646f42dff37fa8700577f09060e001610ee5565b6113ac6123e3565b6113b4612440565b6103e88111156113e25760405163211a907760e11b8152600481018290526103e86024820152604401610bdf565b6113f181600160000154612481565b600180549082905560028290556040805160a08082526006908201526562757946656560d01b60c0820152602081018390529081018390523360608201524260808201527fae95575a673d4e1b8078cc03b3ca2acaffe6d26625496c7bc59d338ff09a4a179060e001610ee5565b6114676123e3565b6001600160a01b03821660009081526018602052604090205461148e90829060ff166127bd565b6001600160a01b038216600081815260186020908152604091829020805485151560ff1982168117909255835160c0808252601390820152721a5cd15e195b5c1d15d85b1b195d131a5b5a5d606a1b60e08201529283019490945260ff9093168015159282019290925260608101929092523360808301524260a0830152907f59efce2bd92f91881f8f3ffb8c70709a05ae83006301d26f9fe6170f3e690aea9061010001611123565b6115406123e3565b6001600160a01b03821660009081526016602052604090205461156790829060ff166127bd565b306001600160a01b0316826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d391906132f4565b6001600160a01b03161415801561165d5750306001600160a01b0316826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561162d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165191906132f4565b6001600160a01b031614155b1561168657604051634726455360e11b81526001600160a01b0383166004820152602401610bdf565b6013546001600160a01b031660009081526016602052604090205460ff166116ce576013546001600160a01b03166000908152601860205260409020805460ff191660011790555b6001600160a01b038216600081815260166020908152604091829020805485151560ff1982168117909255835160c08082526008908201526706973506169724c560c41b60e08201529283019490945260ff9093168015159282019290925260608101929092523360808301524260a0830152907f59efce2bd92f91881f8f3ffb8c70709a05ae83006301d26f9fe6170f3e690aea9061010001611123565b6117756128b0565b61177f60006128ec565b565b6117896123e3565b612710611794611d48565b61179f90600a61327f565b6117a99190613296565b8111156117cc5760405163181c9d0b60e21b815260048101829052602401610bdf565b6117d881600f54612481565b600f805490829055604080518281526020810184905233918101919091524260608201527f9a9f4704ac409fe039e92a996e415370980275aaff2992936ed5b432886c55c590608001610ee5565b61182e6123e3565b611836612867565b60135461184e908290600160d01b900460ff166127bd565b60138054821515600160d01b81810260ff60d01b1984161784556040805160a080825281019590955272697357616c6c65744c696d697441637469766560681b60c086015260ff9190930416801515602085015291830152336060830152426080830152907fda986e332f97963bfa4bb220bda255b40296aa680cff592b805c2deb80b1dbf39060e001610ee5565b6118e56123e3565b6118ed61293c565b6013805460ff60c01b1916600160c01b1790556040805160608082526010908201526f1a5cd1985a5b1cd85999531bd8dad95960821b608082015233602082015242918101919091526000805160206133d58339815191529060a0015b60405180910390a1565b61195c6123e3565b611964612440565b6103e88111156119925760405163211a907760e11b8152600481018290526103e86024820152604401610bdf565b6119a181600560000154612481565b600580549082905560068290556040805160a0808252600b908201526a7472616e7366657246656560a81b60c0820152602081018390529081018390523360608201524260808201527fae95575a673d4e1b8078cc03b3ca2acaffe6d26625496c7bc59d338ff09a4a179060e001610ee5565b601354600160a01b900460ff1615611a5857601354600d5460405163e39c1e8760e01b8152600160a01b90920460ff16151560048301526024820152604401610bdf565b6000546001600160a01b031615801590611a8c575033611a806000546001600160a01b031690565b6001600160a01b031614155b8015611ac3575042611ac17f000000000000000000000000000000000000000000000000000000000000000062278d006132cb565b115b15611ae35760405163118cdaa760e01b8152336004820152602401610bdf565b6000546001600160a01b0316158015611b16575033611b0a6000546001600160a01b031690565b6001600160a01b031614155b8015611b4d575042611b4b7f00000000000000000000000000000000000000000000000000000000000000006213c6806132cb565b115b15611bd957611b7f7f00000000000000000000000000000000000000000000000000000000000000006213c6806132cb565b42611bad7f00000000000000000000000000000000000000000000000000000000000000006213c6806132cb565b611bb791906132b8565b604051636ddcad9f60e01b815260048101929092526024820152604401610bdf565b601354600160d01b900460ff16611bfe576013805460ff60d01b1916600160d01b1790555b601354600160a81b900460ff16611c23576013805460ff60a81b1916600160a81b1790555b601354600160d81b900460ff16611c48576013805460ff60d81b1916600160d81b1790555b6013805460ff60a01b1916600160a01b17905542600d81905543600e556040805133815260208101929092527f8b70aa279b24da71d8a874fa0b0ee8f1a587c4fb32b80d87e95cdbdae01b7b4f910161194a565b611ca46123e3565b601354611cbc908290600160d81b900460ff166127bd565b60138054821515600160d81b81810260ff60d81b198416179093556040805160a0808252600d908201526c1a5cd4ddd85c115b98589b1959609a1b60c082015260ff94909304939093168015156020840152928201523360608201524260808201527fda986e332f97963bfa4bb220bda255b40296aa680cff592b805c2deb80b1dbf39060e001610ee5565b60146020527f4f26c3876aa9f4b92579780beea1161a61f87ebf1ec6ee865b299e447ecba99c5461dead60009081527f8b9e18c5e04efe171d1e4f682ad90d753958a5ffe56db5290b0236c8e0b6db0054600c54919291611da991906132b8565b611db391906132b8565b905090565b611dc06123e3565b611dc8612867565b6013805460ff60c81b1916600160c81b178155604080516060808252810192909252721a5cd5d85b1b195d131a5b5a5d131bd8dad959606a1b608083015233602083015242908201526000805160206133d58339815191529060a00161194a565b600033610e2181858561256e565b611e3f6128b0565b611e47612440565b6013805460ff60b01b1916600160b01b179055604080516060808252600b908201526a1a5cd19959531bd8dad95960aa1b608082015233602082015242918101919091526000805160206133d58339815191529060a00161194a565b611eab6123e3565b6001600160a01b038116611edd57604051634726455360e11b81526001600160a01b0382166004820152602401610bdf565b600b54611ef49082906001600160a01b031661282a565b600b80546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935233918101919091524260608201527fe1cb783288eddc7b22c25642a832d886a558be0dd900747310a34156b9fdcbbb9060800160405180910390a1600b546040805163c45a015560e01b815290516000926001600160a01b03169163c45a01559160048083019260209291908290030181865afa158015611fab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcf91906132f4565b6001600160a01b031663e6a4390530600b60009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612031573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205591906132f4565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa1580156120a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c491906132f4565b6001600160a01b0316036122e357600b60009054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015612125573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214991906132f4565b6001600160a01b031663c9c6539630600b60009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121cf91906132f4565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af115801561221c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224091906132f4565b601380546001600160a01b0319166001600160a01b0392909216918217905560009081526018602052604090205460ff1661229b576013546001600160a01b03166000908152601860205260409020805460ff191660011790555b6013546001600160a01b031660009081526016602052604090205460ff166122e3576013546001600160a01b03166000908152601660205260409020805460ff191660011790555b5050565b6122ef6128b0565b6013805460ff60b81b1916600160b81b1790556040805160608082526010908201526f1a5cd49958d95a5d995c931bd8dad95960821b608082015233602082015242918101919091526000805160206133d58339815191529060a00161194a565b6123586128b0565b61deac196001600160a01b0382160161238f57604051634726455360e11b81526001600160a01b0382166004820152602401610bdf565b6123aa816123a56000546001600160a01b031690565b61282a565b601180546001600160a01b0319166001600160a01b0383161790556123ce81612982565b50565b6123de83838360016129bd565b505050565b6123eb61293c565b6011546001600160a01b031633148015906124205750336124146000546001600160a01b031690565b6001600160a01b031614155b1561177f5760405163118cdaa760e01b8152336004820152602401610bdf565b601354600160b01b900460ff161561177f576040516354f3dc5160e11b815260206004820152600360248201526246656560e81b6044820152606401610bdf565b8082036122e35760405163657e16cf60e01b815260048101839052602401610bdf565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526123de908490612a92565b6001600160a01b03838116600090815260156020908152604080832093861683529290522054600019811461102a578181101561255f57604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610bdf565b61102a848484840360006129bd565b6001600160a01b03831661259857604051634b637e8f60e11b815260006004820152602401610bdf565b6001600160a01b0382166125c25760405163ec442f0560e01b815260006004820152602401610bdf565b601354600160a01b900460ff16612633576001600160a01b03831660009081526017602052604090205460ff1615801561261557506001600160a01b03821660009081526017602052604090205460ff16155b156126335760405163ab9827ff60e01b815260040160405180910390fd5b601354600160e01b900460ff168061266357506001600160a01b03831660009081526017602052604090205460ff165b15612673576123de838383612af5565b6013546001600160a01b0384811691161480159061269a5750601354600160d81b900460ff165b80156126b75750600f54600a546008546126b491906132b8565b10155b80156126d45750600f543060009081526014602052604090205410155b1561274657600f54601354600160c01b900460ff1680156126fe57506000546001600160a01b0316155b1561273b576000612710612710611d48565b61271b90600a61327f565b6127259190613296565b9050818111156127355781612737565b805b9150505b61274481610b81565b505b6013548190600160a81b900460ff16801561277a57506001600160a01b03841660009081526017602052604090205460ff16155b801561279f57506001600160a01b03831660009081526017602052604090205460ff16155b156127b2576127af848484612cbd565b90505b61102a848483612af5565b801515821515036122e35760405162a7e72d60e41b81528215156004820152602401610bdf565b601354600160b81b900460ff161561177f576040516354f3dc5160e11b81526020600482015260086024820152672932b1b2b4bb32b960c11b6044820152606401610bdf565b806001600160a01b0316826001600160a01b0316036122e35760405163a936636960e01b81526001600160a01b0383166004820152602401610bdf565b601354600160c81b900460ff161561177f576040516354f3dc5160e11b815260206004820152600b60248201526a15d85b1b195d131a5b5a5d60aa1b6044820152606401610bdf565b336128c36000546001600160a01b031690565b6001600160a01b03161461177f5760405163118cdaa760e01b8152336004820152602401610bdf565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b601354600160c01b900460ff161561177f576040516354f3dc5160e11b81526020600482015260086024820152674661696c7361666560c01b6044820152606401610bdf565b61298a6128b0565b6001600160a01b0381166129b457604051631e4fbdf760e01b815260006004820152602401610bdf565b6123ce816128ec565b6001600160a01b0384166129e75760405163e602df0560e01b815260006004820152602401610bdf565b6001600160a01b038316612a1157604051634a1406b160e11b815260006004820152602401610bdf565b6001600160a01b038085166000908152601560209081526040808320938716835292905220829055801561102a57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051612a8491815260200190565b60405180910390a350505050565b6000612aa76001600160a01b03841683612dbc565b90508051600014158015612acc575080806020019051810190612aca919061339b565b155b156123de57604051635274afe760e01b81526001600160a01b0384166004820152602401610bdf565b6001600160a01b038216600090815260146020526040812054612b199083906132cb565b90506000612710601054612b2b611d48565b612b35919061327f565b612b3f9190613296565b90508082118015612b6957506001600160a01b03841660009081526018602052604090205460ff16155b15612b9157604051633045819360e21b81526004810183905260248101829052604401610bdf565b6001600160a01b038516612bbc5782600c6000828254612bb191906132cb565b90915550612c2e9050565b6001600160a01b03851660009081526014602052604090205483811015612c0f5760405163391434e360e21b81526001600160a01b03871660048201526024810182905260448101859052606401610bdf565b6001600160a01b03861660009081526014602052604090209084900390555b6001600160a01b038416612c4a57600c80548490039055612c69565b6001600160a01b03841660009081526014602052604090208054840190555b836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051612cae91815260200190565b60405180910390a35050505050565b6013805460ff60e01b1916600160e01b1790556001600160a01b03831660009081526016602052604081205460ff168015612cf9575060015415155b15612d0f57612d088483612dca565b9050612da8565b6001600160a01b03831660009081526016602052604090205460ff168015612d38575060035415155b15612d4757612d088483612e02565b6001600160a01b03841660009081526016602052604090205460ff16158015612d8957506001600160a01b03831660009081526016602052604090205460ff16155b8015612d96575060055415155b15612da557612d088483612e3a565b50805b6013805460ff60e01b191690559392505050565b606061104f83836000612e72565b6013805460ff60e01b1916600160e01b1790556040805180820190915260015481526002546020820152600090612da8908484612f0f565b6013805460ff60e01b1916600160e01b1790556040805180820190915260035481526004546020820152600090612da8908484612f0f565b6013805460ff60e01b1916600160e01b1790556040805180820190915260055481526006546020820152600090612da8908484612f0f565b606081471015612e975760405163cd78605960e01b8152306004820152602401610bdf565b600080856001600160a01b03168486604051612eb391906133b8565b60006040518083038185875af1925050503d8060008114612ef0576040519150601f19603f3d011682016040523d82523d6000602084013e612ef5565b606091505b5091509150612f05868383612f92565b9695505050505050565b6013805460ff60e01b1916600160e01b1790558251600e5460009190612f3590836132cb565b4311612f4057506126ac5b6000612710612f4f838661327f565b612f599190613296565b90506000612f6782866132b8565b90508115612f7b57612f7b87878486612fee565b6013805460ff60e01b191690559695505050505050565b606082612fa757612fa282613047565b61104f565b8151158015612fbe57506001600160a01b0384163b155b15612fe757604051639996b31560e01b81526001600160a01b0385166004820152602401610bdf565b508061104f565b6013805460ff60e01b1916600160e01b17905583516000908290613012908561327f565b61301c9190613296565b90506130288184613070565b613033843085612af5565b50506013805460ff60e01b19169055505050565b8051156130575780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6013805460ff60e01b1916600160e01b179055600780548391906000906130989084906132cb565b9091555050600880548291906000906130b29084906132cb565b90915550506013805460ff60e01b191690555050565b6000602082840312156130da57600080fd5b5035919050565b60005b838110156130fc5781810151838201526020016130e4565b50506000910152565b60208152600082518060208401526131248160408501602087016130e1565b601f01601f19169190910160400192915050565b6001600160a01b03811681146123ce57600080fd5b60006020828403121561315f57600080fd5b813561104f81613138565b6000806040838503121561317d57600080fd5b823561318881613138565b946020939093013593505050565b6000806000606084860312156131ab57600080fd5b83356131b681613138565b925060208401356131c681613138565b929592945050506040919091013590565b80151581146123ce57600080fd5b600080604083850312156131f857600080fd5b823561320381613138565b91506020830135613213816131d7565b809150509250929050565b60006020828403121561323057600080fd5b813561104f816131d7565b6000806040838503121561324e57600080fd5b823561325981613138565b9150602083013561321381613138565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610e2757610e27613269565b6000826132b357634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610e2757610e27613269565b80820180821115610e2757610e27613269565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561330657600080fd5b815161104f81613138565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156133615784516001600160a01b03168352938301939183019160010161333c565b50506001600160a01b03969096166060850152505050608001529392505050565b60006020828403121561339457600080fd5b5051919050565b6000602082840312156133ad57600080fd5b815161104f816131d7565b600082516133ca8184602087016130e1565b919091019291505056fe611312486a6540001c2b69bc849753e64cdefc853bbbc7a576d987821aec28b4a26469706673582212204eb8aa1cb488225b8d42eae37fd40524baf6888b787990af6d0d0fa98d42e9a564736f6c63430008120033

Deployed Bytecode

0x60806040526004361061039b5760003560e01c8063891ff84a116101dc578063acb2ad6f11610102578063dd62ed3e116100a0578063e811f50a1161006f578063e811f50a14610b10578063f2c4220e14610b2b578063f2fde38b14610b41578063f887ea4014610b6157600080fd5b8063dd62ed3e14610a67578063e2924cd114610aad578063e43504da14610ace578063e79f53e614610aef57600080fd5b8063cf9769fd116100dc578063cf9769fd146109f5578063d621e81314610a0a578063d830678614610a2b578063d941907114610a4c57600080fd5b8063acb2ad6f14610999578063b908de8c146109b4578063c851cc32146109d557600080fd5b80639ffe05331161017a578063a8aa1b3111610149578063a8aa1b311461092e578063a9059cbb1461094e578063ab28a04c1461096e578063ab3662921461098457600080fd5b80639ffe0533146108b8578063a4475ce4146108d9578063a5949bcf146108f9578063a616162a1461091957600080fd5b8063924de9b7116101b6578063924de9b7146108255780639358928b1461084557806395d89b411461085a578063999969731461088857600080fd5b8063891ff84a146107ae5780638a8c523c146107de5780638da5cb5b146107f357600080fd5b80633d6362d6116102c157806366a88d961161025f578063779e80d51161022e578063779e80d5146107255780637a40624b146107455780637e2b16d1146107795780638577a6d51461078e57600080fd5b806366a88d96146106a457806370a08231146106ba578063715018a6146106f057806375fed3c71461070557600080fd5b8063470624021161029b57806347062402146106335780634b7e71b31461064e57806359cd90311461066e578063625dd6051461068457600080fd5b80633d6362d6146105d35780634324deae146105f3578063467abe0a1461061357600080fd5b806323b872dd11610339578063313ce56711610308578063313ce56714610556578063351a964d14610572578063355496ca146105935780633bf31454146105b357600080fd5b806323b872dd146104cf5780632b14ca56146104ef5780632c735ef81461051f578063312579661461053557600080fd5b8063095ea7b311610375578063095ea7b31461045057806318160ddd146104705780631d933a4a1461048f5780631f685bac146104af57600080fd5b806301295143146103a757806306fdde03146103c957806308c436501461041057600080fd5b366103a257005b600080fd5b3480156103b357600080fd5b506103c76103c23660046130c8565b610b81565b005b3480156103d557600080fd5b5060408051808201909152600c81526b44656570536f75746820414960a01b60208201525b6040516104079190613105565b60405180910390f35b34801561041c57600080fd5b5061044061042b36600461314d565b60166020526000908152604090205460ff1681565b6040519015158152602001610407565b34801561045c57600080fd5b5061044061046b36600461316a565b610e13565b34801561047c57600080fd5b50600c545b604051908152602001610407565b34801561049b57600080fd5b506103c76104aa3660046130c8565b610e2d565b3480156104bb57600080fd5b506103c76104ca36600461316a565b610ef1565b3480156104db57600080fd5b506104406104ea366004613196565b611030565b3480156104fb57600080fd5b5060035460045461050a919082565b60408051928352602083019190915201610407565b34801561052b57600080fd5b50610481600d5481565b34801561054157600080fd5b5060135461044090600160c81b900460ff1681565b34801561056257600080fd5b5060405160128152602001610407565b34801561057e57600080fd5b5060135461044090600160d81b900460ff1681565b34801561059f57600080fd5b506103c76105ae3660046131e5565b611056565b3480156105bf57600080fd5b506103c76105ce36600461321e565b611130565b3480156105df57600080fd5b506103c76105ee36600461314d565b6111e2565b3480156105ff57600080fd5b506103c761060e3660046130c8565b6112eb565b34801561061f57600080fd5b506103c761062e3660046130c8565b6113a4565b34801561063f57600080fd5b5060015460025461050a919082565b34801561065a57600080fd5b506103c76106693660046131e5565b61145f565b34801561067a57600080fd5b50610481600f5481565b34801561069057600080fd5b506103c761069f3660046131e5565b611538565b3480156106b057600080fd5b5061048160105481565b3480156106c657600080fd5b506104816106d536600461314d565b6001600160a01b031660009081526014602052604090205490565b3480156106fc57600080fd5b506103c761176d565b34801561071157600080fd5b506103c76107203660046130c8565b611781565b34801561073157600080fd5b506103c761074036600461321e565b611826565b34801561075157600080fd5b506104817f00000000000000000000000000000000000000000000000000000000659740af81565b34801561078557600080fd5b506103c76118dd565b34801561079a57600080fd5b506103c76107a93660046130c8565b611954565b3480156107ba57600080fd5b506104406107c936600461314d565b60176020526000908152604090205460ff1681565b3480156107ea57600080fd5b506103c7611a14565b3480156107ff57600080fd5b506000546001600160a01b03165b6040516001600160a01b039091168152602001610407565b34801561083157600080fd5b506103c761084036600461321e565b611c9c565b34801561085157600080fd5b50610481611d48565b34801561086657600080fd5b506040805180820190915260058152640a69eaaa8960db1b60208201526103fa565b34801561089457600080fd5b506104406108a336600461314d565b60186020526000908152604090205460ff1681565b3480156108c457600080fd5b5060135461044090600160d01b900460ff1681565b3480156108e557600080fd5b5060115461080d906001600160a01b031681565b34801561090557600080fd5b5060125461080d906001600160a01b031681565b34801561092557600080fd5b506103c7611db8565b34801561093a57600080fd5b5060135461080d906001600160a01b031681565b34801561095a57600080fd5b5061044061096936600461316a565b611e29565b34801561097a57600080fd5b5061048161271081565b34801561099057600080fd5b506103c7611e37565b3480156109a557600080fd5b5060055460065461050a919082565b3480156109c057600080fd5b5060135461044090600160b01b900460ff1681565b3480156109e157600080fd5b506103c76109f036600461314d565b611ea3565b348015610a0157600080fd5b506103c76122e7565b348015610a1657600080fd5b5060135461044090600160a01b900460ff1681565b348015610a3757600080fd5b5060135461044090600160e01b900460ff1681565b348015610a5857600080fd5b50600954600a5461050a919082565b348015610a7357600080fd5b50610481610a8236600461323b565b6001600160a01b03918216600090815260156020908152604080832093909416825291909152205490565b348015610ab957600080fd5b5060135461044090600160b81b900460ff1681565b348015610ada57600080fd5b5060135461044090600160a81b900460ff1681565b348015610afb57600080fd5b5060135461044090600160c01b900460ff1681565b348015610b1c57600080fd5b5060075460085461050a919082565b348015610b3757600080fd5b50610481600e5481565b348015610b4d57600080fd5b506103c7610b5c36600461314d565b612350565b348015610b6d57600080fd5b50600b5461080d906001600160a01b031681565b6013805460ff60e01b1916600160e01b1790556000612710610ba1611d48565b610bac90603261327f565b610bb69190613296565b905080821115610be85760405163179b4ccd60e31b815260048101839052602481018290526044015b60405180910390fd5b600954600754600091610bfa916132b8565b600a54600854919250600091610c1091906132b8565b9050600081610c1f848761327f565b610c299190613296565b90508060096000016000828254610c4091906132cb565b9091555050600a8054869190600090610c5a9084906132cb565b90915550506040805160028082526060820183526000926020830190803683370190505090503081600081518110610c9457610c946132de565b6001600160a01b03928316602091820292909201810191909152600b54604080516315ab88c960e31b81529051919093169263ad5c46489260048083019391928290030181865afa158015610ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1191906132f4565b81600181518110610d2457610d246132de565b6001600160a01b039283166020918202929092010152600b54610d4a91309116886123d1565b6040805183815260208101889052338183015242606082015290517fb933c1b294702108551eddf782a9c7d1a018b57f68ecf63bc59a1247daa19c309181900360800190a1600b5460125460405163791ac94760e01b81526001600160a01b039283169263791ac94792610dcc92879260009288929116904290600401613311565b600060405180830381600087803b158015610de657600080fd5b505af1158015610dfa573d6000803e3d6000fd5b50506013805460ff60e01b191690555050505050505050565b600033610e218185856123d1565b60019150505b92915050565b610e356123e3565b610e3d612440565b6103e8811115610e6b5760405163211a907760e11b8152600481018290526103e86024820152604401610bdf565b610e7a81600360000154612481565b600380549082905560048290556040805160a08082526007908201526673656c6c46656560c81b60c0820152602081018390529081018390523360608201524260808201527fae95575a673d4e1b8078cc03b3ca2acaffe6d26625496c7bc59d338ff09a4a179060e0015b60405180910390a15050565b60125481906001600160a01b03908116903090851603610f24576040516315ea636560e31b815260040160405180910390fd5b6001600160a01b038416610fa35782600003610f3e574791505b6001600160a01b0381163303610f675760405163a5eb0da960e01b815260040160405180910390fd5b6040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015610f9d573d6000803e3d6000fd5b5061102a565b82600003611016576040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015610fef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110139190613382565b91505b61102a6001600160a01b03851682846124a4565b50505050565b60003361103e8582856124f6565b61104985858561256e565b60019150505b9392505050565b61105e6123e3565b6001600160a01b03821660009081526017602052604090205461108590829060ff166127bd565b6001600160a01b038216600081815260176020908152604091829020805485151560ff1982168117909255835160c0808252600b908201526a69734578656d707446656560a81b60e08201529283019490945260ff9093168015159282019290925260608101929092523360808301524260a0830152907f59efce2bd92f91881f8f3ffb8c70709a05ae83006301d26f9fe6170f3e690aea90610100015b60405180910390a1505050565b6111386123e3565b611140612440565b601354611158908290600160a81b900460ff166127bd565b60138054821515600160a81b81810260ff60a81b198416179093556040805160a0808252600b908201526a697346656541637469766560a81b60c082015260ff94909304939093168015156020840152928201523360608201524260808201527fda986e332f97963bfa4bb220bda255b40296aa680cff592b805c2deb80b1dbf39060e001610ee5565b6111ea6123e3565b6001600160a01b0381163b156112135760405163259f1ec560e01b815260040160405180910390fd5b6001600160a01b03811661123d57604051634726455360e11b815260006004820152602401610bdf565b6112456127e4565b60125461125c9082906001600160a01b031661282a565b601280546001600160a01b031981166001600160a01b038481169182179093556040805160a08082526011908201527036b0b935b2ba34b733a932b1b2b4bb32b960791b60c0820152939092166020840181905291830152336060830152426080830152907ff7df6bc5c0f9735c300a374247b60dcacf1942b6031785957e762d77977ed4209060e001610ee5565b6112f36123e3565b606481101561131f5760405163ab7d1fbb60e01b81526004810182905260646024820152604401610bdf565b611327612867565b61133381601054612481565b60108054908290556040805160a0808252600e908201526d1b585e15d85b1b195d131a5b5a5d60921b60c0820152602081018390529081018390523360608201524260808201527f18558967fd5a093126ad115ffea8d443544786d34a646f42dff37fa8700577f09060e001610ee5565b6113ac6123e3565b6113b4612440565b6103e88111156113e25760405163211a907760e11b8152600481018290526103e86024820152604401610bdf565b6113f181600160000154612481565b600180549082905560028290556040805160a08082526006908201526562757946656560d01b60c0820152602081018390529081018390523360608201524260808201527fae95575a673d4e1b8078cc03b3ca2acaffe6d26625496c7bc59d338ff09a4a179060e001610ee5565b6114676123e3565b6001600160a01b03821660009081526018602052604090205461148e90829060ff166127bd565b6001600160a01b038216600081815260186020908152604091829020805485151560ff1982168117909255835160c0808252601390820152721a5cd15e195b5c1d15d85b1b195d131a5b5a5d606a1b60e08201529283019490945260ff9093168015159282019290925260608101929092523360808301524260a0830152907f59efce2bd92f91881f8f3ffb8c70709a05ae83006301d26f9fe6170f3e690aea9061010001611123565b6115406123e3565b6001600160a01b03821660009081526016602052604090205461156790829060ff166127bd565b306001600160a01b0316826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d391906132f4565b6001600160a01b03161415801561165d5750306001600160a01b0316826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561162d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165191906132f4565b6001600160a01b031614155b1561168657604051634726455360e11b81526001600160a01b0383166004820152602401610bdf565b6013546001600160a01b031660009081526016602052604090205460ff166116ce576013546001600160a01b03166000908152601860205260409020805460ff191660011790555b6001600160a01b038216600081815260166020908152604091829020805485151560ff1982168117909255835160c08082526008908201526706973506169724c560c41b60e08201529283019490945260ff9093168015159282019290925260608101929092523360808301524260a0830152907f59efce2bd92f91881f8f3ffb8c70709a05ae83006301d26f9fe6170f3e690aea9061010001611123565b6117756128b0565b61177f60006128ec565b565b6117896123e3565b612710611794611d48565b61179f90600a61327f565b6117a99190613296565b8111156117cc5760405163181c9d0b60e21b815260048101829052602401610bdf565b6117d881600f54612481565b600f805490829055604080518281526020810184905233918101919091524260608201527f9a9f4704ac409fe039e92a996e415370980275aaff2992936ed5b432886c55c590608001610ee5565b61182e6123e3565b611836612867565b60135461184e908290600160d01b900460ff166127bd565b60138054821515600160d01b81810260ff60d01b1984161784556040805160a080825281019590955272697357616c6c65744c696d697441637469766560681b60c086015260ff9190930416801515602085015291830152336060830152426080830152907fda986e332f97963bfa4bb220bda255b40296aa680cff592b805c2deb80b1dbf39060e001610ee5565b6118e56123e3565b6118ed61293c565b6013805460ff60c01b1916600160c01b1790556040805160608082526010908201526f1a5cd1985a5b1cd85999531bd8dad95960821b608082015233602082015242918101919091526000805160206133d58339815191529060a0015b60405180910390a1565b61195c6123e3565b611964612440565b6103e88111156119925760405163211a907760e11b8152600481018290526103e86024820152604401610bdf565b6119a181600560000154612481565b600580549082905560068290556040805160a0808252600b908201526a7472616e7366657246656560a81b60c0820152602081018390529081018390523360608201524260808201527fae95575a673d4e1b8078cc03b3ca2acaffe6d26625496c7bc59d338ff09a4a179060e001610ee5565b601354600160a01b900460ff1615611a5857601354600d5460405163e39c1e8760e01b8152600160a01b90920460ff16151560048301526024820152604401610bdf565b6000546001600160a01b031615801590611a8c575033611a806000546001600160a01b031690565b6001600160a01b031614155b8015611ac3575042611ac17f00000000000000000000000000000000000000000000000000000000659740af62278d006132cb565b115b15611ae35760405163118cdaa760e01b8152336004820152602401610bdf565b6000546001600160a01b0316158015611b16575033611b0a6000546001600160a01b031690565b6001600160a01b031614155b8015611b4d575042611b4b7f00000000000000000000000000000000000000000000000000000000659740af6213c6806132cb565b115b15611bd957611b7f7f00000000000000000000000000000000000000000000000000000000659740af6213c6806132cb565b42611bad7f00000000000000000000000000000000000000000000000000000000659740af6213c6806132cb565b611bb791906132b8565b604051636ddcad9f60e01b815260048101929092526024820152604401610bdf565b601354600160d01b900460ff16611bfe576013805460ff60d01b1916600160d01b1790555b601354600160a81b900460ff16611c23576013805460ff60a81b1916600160a81b1790555b601354600160d81b900460ff16611c48576013805460ff60d81b1916600160d81b1790555b6013805460ff60a01b1916600160a01b17905542600d81905543600e556040805133815260208101929092527f8b70aa279b24da71d8a874fa0b0ee8f1a587c4fb32b80d87e95cdbdae01b7b4f910161194a565b611ca46123e3565b601354611cbc908290600160d81b900460ff166127bd565b60138054821515600160d81b81810260ff60d81b198416179093556040805160a0808252600d908201526c1a5cd4ddd85c115b98589b1959609a1b60c082015260ff94909304939093168015156020840152928201523360608201524260808201527fda986e332f97963bfa4bb220bda255b40296aa680cff592b805c2deb80b1dbf39060e001610ee5565b60146020527f4f26c3876aa9f4b92579780beea1161a61f87ebf1ec6ee865b299e447ecba99c5461dead60009081527f8b9e18c5e04efe171d1e4f682ad90d753958a5ffe56db5290b0236c8e0b6db0054600c54919291611da991906132b8565b611db391906132b8565b905090565b611dc06123e3565b611dc8612867565b6013805460ff60c81b1916600160c81b178155604080516060808252810192909252721a5cd5d85b1b195d131a5b5a5d131bd8dad959606a1b608083015233602083015242908201526000805160206133d58339815191529060a00161194a565b600033610e2181858561256e565b611e3f6128b0565b611e47612440565b6013805460ff60b01b1916600160b01b179055604080516060808252600b908201526a1a5cd19959531bd8dad95960aa1b608082015233602082015242918101919091526000805160206133d58339815191529060a00161194a565b611eab6123e3565b6001600160a01b038116611edd57604051634726455360e11b81526001600160a01b0382166004820152602401610bdf565b600b54611ef49082906001600160a01b031661282a565b600b80546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935233918101919091524260608201527fe1cb783288eddc7b22c25642a832d886a558be0dd900747310a34156b9fdcbbb9060800160405180910390a1600b546040805163c45a015560e01b815290516000926001600160a01b03169163c45a01559160048083019260209291908290030181865afa158015611fab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcf91906132f4565b6001600160a01b031663e6a4390530600b60009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612031573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205591906132f4565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa1580156120a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c491906132f4565b6001600160a01b0316036122e357600b60009054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015612125573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214991906132f4565b6001600160a01b031663c9c6539630600b60009054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121cf91906132f4565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af115801561221c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224091906132f4565b601380546001600160a01b0319166001600160a01b0392909216918217905560009081526018602052604090205460ff1661229b576013546001600160a01b03166000908152601860205260409020805460ff191660011790555b6013546001600160a01b031660009081526016602052604090205460ff166122e3576013546001600160a01b03166000908152601660205260409020805460ff191660011790555b5050565b6122ef6128b0565b6013805460ff60b81b1916600160b81b1790556040805160608082526010908201526f1a5cd49958d95a5d995c931bd8dad95960821b608082015233602082015242918101919091526000805160206133d58339815191529060a00161194a565b6123586128b0565b61deac196001600160a01b0382160161238f57604051634726455360e11b81526001600160a01b0382166004820152602401610bdf565b6123aa816123a56000546001600160a01b031690565b61282a565b601180546001600160a01b0319166001600160a01b0383161790556123ce81612982565b50565b6123de83838360016129bd565b505050565b6123eb61293c565b6011546001600160a01b031633148015906124205750336124146000546001600160a01b031690565b6001600160a01b031614155b1561177f5760405163118cdaa760e01b8152336004820152602401610bdf565b601354600160b01b900460ff161561177f576040516354f3dc5160e11b815260206004820152600360248201526246656560e81b6044820152606401610bdf565b8082036122e35760405163657e16cf60e01b815260048101839052602401610bdf565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526123de908490612a92565b6001600160a01b03838116600090815260156020908152604080832093861683529290522054600019811461102a578181101561255f57604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610bdf565b61102a848484840360006129bd565b6001600160a01b03831661259857604051634b637e8f60e11b815260006004820152602401610bdf565b6001600160a01b0382166125c25760405163ec442f0560e01b815260006004820152602401610bdf565b601354600160a01b900460ff16612633576001600160a01b03831660009081526017602052604090205460ff1615801561261557506001600160a01b03821660009081526017602052604090205460ff16155b156126335760405163ab9827ff60e01b815260040160405180910390fd5b601354600160e01b900460ff168061266357506001600160a01b03831660009081526017602052604090205460ff165b15612673576123de838383612af5565b6013546001600160a01b0384811691161480159061269a5750601354600160d81b900460ff165b80156126b75750600f54600a546008546126b491906132b8565b10155b80156126d45750600f543060009081526014602052604090205410155b1561274657600f54601354600160c01b900460ff1680156126fe57506000546001600160a01b0316155b1561273b576000612710612710611d48565b61271b90600a61327f565b6127259190613296565b9050818111156127355781612737565b805b9150505b61274481610b81565b505b6013548190600160a81b900460ff16801561277a57506001600160a01b03841660009081526017602052604090205460ff16155b801561279f57506001600160a01b03831660009081526017602052604090205460ff16155b156127b2576127af848484612cbd565b90505b61102a848483612af5565b801515821515036122e35760405162a7e72d60e41b81528215156004820152602401610bdf565b601354600160b81b900460ff161561177f576040516354f3dc5160e11b81526020600482015260086024820152672932b1b2b4bb32b960c11b6044820152606401610bdf565b806001600160a01b0316826001600160a01b0316036122e35760405163a936636960e01b81526001600160a01b0383166004820152602401610bdf565b601354600160c81b900460ff161561177f576040516354f3dc5160e11b815260206004820152600b60248201526a15d85b1b195d131a5b5a5d60aa1b6044820152606401610bdf565b336128c36000546001600160a01b031690565b6001600160a01b03161461177f5760405163118cdaa760e01b8152336004820152602401610bdf565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b601354600160c01b900460ff161561177f576040516354f3dc5160e11b81526020600482015260086024820152674661696c7361666560c01b6044820152606401610bdf565b61298a6128b0565b6001600160a01b0381166129b457604051631e4fbdf760e01b815260006004820152602401610bdf565b6123ce816128ec565b6001600160a01b0384166129e75760405163e602df0560e01b815260006004820152602401610bdf565b6001600160a01b038316612a1157604051634a1406b160e11b815260006004820152602401610bdf565b6001600160a01b038085166000908152601560209081526040808320938716835292905220829055801561102a57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051612a8491815260200190565b60405180910390a350505050565b6000612aa76001600160a01b03841683612dbc565b90508051600014158015612acc575080806020019051810190612aca919061339b565b155b156123de57604051635274afe760e01b81526001600160a01b0384166004820152602401610bdf565b6001600160a01b038216600090815260146020526040812054612b199083906132cb565b90506000612710601054612b2b611d48565b612b35919061327f565b612b3f9190613296565b90508082118015612b6957506001600160a01b03841660009081526018602052604090205460ff16155b15612b9157604051633045819360e21b81526004810183905260248101829052604401610bdf565b6001600160a01b038516612bbc5782600c6000828254612bb191906132cb565b90915550612c2e9050565b6001600160a01b03851660009081526014602052604090205483811015612c0f5760405163391434e360e21b81526001600160a01b03871660048201526024810182905260448101859052606401610bdf565b6001600160a01b03861660009081526014602052604090209084900390555b6001600160a01b038416612c4a57600c80548490039055612c69565b6001600160a01b03841660009081526014602052604090208054840190555b836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051612cae91815260200190565b60405180910390a35050505050565b6013805460ff60e01b1916600160e01b1790556001600160a01b03831660009081526016602052604081205460ff168015612cf9575060015415155b15612d0f57612d088483612dca565b9050612da8565b6001600160a01b03831660009081526016602052604090205460ff168015612d38575060035415155b15612d4757612d088483612e02565b6001600160a01b03841660009081526016602052604090205460ff16158015612d8957506001600160a01b03831660009081526016602052604090205460ff16155b8015612d96575060055415155b15612da557612d088483612e3a565b50805b6013805460ff60e01b191690559392505050565b606061104f83836000612e72565b6013805460ff60e01b1916600160e01b1790556040805180820190915260015481526002546020820152600090612da8908484612f0f565b6013805460ff60e01b1916600160e01b1790556040805180820190915260035481526004546020820152600090612da8908484612f0f565b6013805460ff60e01b1916600160e01b1790556040805180820190915260055481526006546020820152600090612da8908484612f0f565b606081471015612e975760405163cd78605960e01b8152306004820152602401610bdf565b600080856001600160a01b03168486604051612eb391906133b8565b60006040518083038185875af1925050503d8060008114612ef0576040519150601f19603f3d011682016040523d82523d6000602084013e612ef5565b606091505b5091509150612f05868383612f92565b9695505050505050565b6013805460ff60e01b1916600160e01b1790558251600e5460009190612f3590836132cb565b4311612f4057506126ac5b6000612710612f4f838661327f565b612f599190613296565b90506000612f6782866132b8565b90508115612f7b57612f7b87878486612fee565b6013805460ff60e01b191690559695505050505050565b606082612fa757612fa282613047565b61104f565b8151158015612fbe57506001600160a01b0384163b155b15612fe757604051639996b31560e01b81526001600160a01b0385166004820152602401610bdf565b508061104f565b6013805460ff60e01b1916600160e01b17905583516000908290613012908561327f565b61301c9190613296565b90506130288184613070565b613033843085612af5565b50506013805460ff60e01b19169055505050565b8051156130575780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6013805460ff60e01b1916600160e01b179055600780548391906000906130989084906132cb565b9091555050600880548291906000906130b29084906132cb565b90915550506013805460ff60e01b191690555050565b6000602082840312156130da57600080fd5b5035919050565b60005b838110156130fc5781810151838201526020016130e4565b50506000910152565b60208152600082518060208401526131248160408501602087016130e1565b601f01601f19169190910160400192915050565b6001600160a01b03811681146123ce57600080fd5b60006020828403121561315f57600080fd5b813561104f81613138565b6000806040838503121561317d57600080fd5b823561318881613138565b946020939093013593505050565b6000806000606084860312156131ab57600080fd5b83356131b681613138565b925060208401356131c681613138565b929592945050506040919091013590565b80151581146123ce57600080fd5b600080604083850312156131f857600080fd5b823561320381613138565b91506020830135613213816131d7565b809150509250929050565b60006020828403121561323057600080fd5b813561104f816131d7565b6000806040838503121561324e57600080fd5b823561325981613138565b9150602083013561321381613138565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610e2757610e27613269565b6000826132b357634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610e2757610e27613269565b80820180821115610e2757610e27613269565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561330657600080fd5b815161104f81613138565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156133615784516001600160a01b03168352938301939183019160010161333c565b50506001600160a01b03969096166060850152505050608001529392505050565b60006020828403121561339457600080fd5b5051919050565b6000602082840312156133ad57600080fd5b815161104f816131d7565b600082516133ca8184602087016130e1565b919091019291505056fe611312486a6540001c2b69bc849753e64cdefc853bbbc7a576d987821aec28b4a26469706673582212204eb8aa1cb488225b8d42eae37fd40524baf6888b787990af6d0d0fa98d42e9a564736f6c63430008120033

Deployed Bytecode Sourcemap

25091:50094:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44567:1148;;;;;;;;;;-1:-1:-1;44567:1148:0;;;;;:::i;:::-;;:::i;:::-;;62223:90;;;;;;;;;;-1:-1:-1;62301:4:0;;;;;;;;;;;;-1:-1:-1;;;62301:4:0;;;;62223:90;;;;;;;:::i;:::-;;;;;;;;26832:45;;;;;;;;;;-1:-1:-1;26832:45:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1408:14:1;;1401:22;1383:41;;1371:2;1356:18;26832:45:0;1243:187:1;65258:194:0;;;;;;;;;;-1:-1:-1;65258:194:0;;;;;:::i;:::-;;:::i;63272:99::-;;;;;;;;;;-1:-1:-1;63351:12:0;;63272:99;;;1901:25:1;;;1889:2;1874:18;63272:99:0;1755:177:1;51641:525:0;;;;;;;;;;-1:-1:-1;51641:525:0;;;;;:::i;:::-;;:::i;38219:801::-;;;;;;;;;;-1:-1:-1;38219:801:0;;;;;:::i;:::-;;:::i;65894:247::-;;;;;;;;;;-1:-1:-1;65894:247:0;;;;;:::i;:::-;;:::i;25397:36::-;;;;;;;;;;-1:-1:-1;25397:36:0;;;;;;;;;;;;;2572:25:1;;;2628:2;2613:18;;2606:34;;;;2545:18;25397:36:0;2398:248:1;25933:33:0;;;;;;;;;;;;;;;;26495:39;;;;;;;;;;-1:-1:-1;26495:39:0;;;;-1:-1:-1;;;26495:39:0;;;;;;62984:90;;;;;;;;;;-1:-1:-1;62984:90:0;;25785:2;2793:36:1;;2781:2;2766:18;62984:90:0;2651:184:1;26587:33:0;;;;;;;;;;-1:-1:-1;26587:33:0;;;;-1:-1:-1;;;26587:33:0;;;;;;56699:337;;;;;;;;;;-1:-1:-1;56699:337:0;;;;;:::i;:::-;;:::i;48099:321::-;;;;;;;;;;-1:-1:-1;48099:321:0;;;;;:::i;:::-;;:::i;53434:657::-;;;;;;;;;;-1:-1:-1;53434:657:0;;;;;:::i;:::-;;:::i;49975:443::-;;;;;;;;;;-1:-1:-1;49975:443:0;;;;;:::i;:::-;;:::i;50769:519::-;;;;;;;;;;-1:-1:-1;50769:519:0;;;;;:::i;:::-;;:::i;25355:35::-;;;;;;;;;;-1:-1:-1;25355:35:0;;;;;;;;;57384:377;;;;;;;;;;-1:-1:-1;57384:377:0;;;;;:::i;:::-;;:::i;26014:36::-;;;;;;;;;;;;;;;;54509:573;;;;;;;;;;-1:-1:-1;54509:573:0;;;;;:::i;:::-;;:::i;26057:35::-;;;;;;;;;;;;;;;;63656:118;;;;;;;;;;-1:-1:-1;63656:118:0;;;;;:::i;:::-;-1:-1:-1;;;;;63748:18:0;63721:7;63748:18;;;:9;:18;;;;;;;63656:118;23260:103;;;;;;;;;;;;;:::i;47408:408::-;;;;;;;;;;-1:-1:-1;47408:408:0;;;;;:::i;:::-;;:::i;48716:369::-;;;;;;;;;;-1:-1:-1;48716:369:0;;;;;:::i;:::-;;:::i;25852:35::-;;;;;;;;;;;;;;;46561:193;;;;;;;;;;;;;:::i;52527:549::-;;;;;;;;;;-1:-1:-1;52527:549:0;;;;;:::i;:::-;;:::i;26884:51::-;;;;;;;;;;-1:-1:-1;26884:51:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;39678:1118;;;;;;;;;;;;;:::i;22546:87::-;;;;;;;;;;-1:-1:-1;22592:7:0;22619:6;-1:-1:-1;;;;;22619:6:0;22546:87;;;-1:-1:-1;;;;;3760:32:1;;;3742:51;;3730:2;3715:18;22546:87:0;3596:203:1;49338:305:0;;;;;;;;;;-1:-1:-1;49338:305:0;;;;;:::i;:::-;;:::i;41192:151::-;;;;;;;;;;;;;:::i;62505:94::-;;;;;;;;;;-1:-1:-1;62585:6:0;;;;;;;;;;;;-1:-1:-1;;;62585:6:0;;;;62505:94;;26942:59;;;;;;;;;;-1:-1:-1;26942:59:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;26541:39;;;;;;;;;;-1:-1:-1;26541:39:0;;;;-1:-1:-1;;;26541:39:0;;;;;;26101:72;;;;;;;;;;-1:-1:-1;26101:72:0;;;;-1:-1:-1;;;;;26101:72:0;;;26180:77;;;;;;;;;;-1:-1:-1;26180:77:0;;;;-1:-1:-1;;;;;26180:77:0;;;46930:205;;;;;;;;;;;;;:::i;26266:19::-;;;;;;;;;;-1:-1:-1;26266:19:0;;;;-1:-1:-1;;;;;26266:19:0;;;64140:186;;;;;;;;;;-1:-1:-1;64140:186:0;;;;;:::i;:::-;;:::i;25796:47::-;;;;;;;;;;;;25837:6;25796:47;;45904:166;;;;;;;;;;;;;:::i;25440:34::-;;;;;;;;;;-1:-1:-1;25440:34:0;;;;;;;;;26371:31;;;;;;;;;;-1:-1:-1;26371:31:0;;;;-1:-1:-1;;;26371:31:0;;;;;;55548:812;;;;;;;;;;-1:-1:-1;55548:812:0;;;;;:::i;:::-;;:::i;46235:155::-;;;;;;;;;;;;;:::i;26294:32::-;;;;;;;;;;-1:-1:-1;26294:32:0;;;;-1:-1:-1;;;26294:32:0;;;;;;26627:26;;;;;;;;;;-1:-1:-1;26627:26:0;;;;-1:-1:-1;;;26627:26:0;;;;;;25523:34;;;;;;;;;;-1:-1:-1;25523:34:0;;;;;;;;;64708:148;;;;;;;;;;-1:-1:-1;64708:148:0;;;;;:::i;:::-;-1:-1:-1;;;;;64818:21:0;;;64791:7;64818:21;;;:11;:21;;;;;;;;:30;;;;;;;;;;;;;64708:148;26409:36;;;;;;;;;;-1:-1:-1;26409:36:0;;;;-1:-1:-1;;;26409:36:0;;;;;;26333:31;;;;;;;;;;-1:-1:-1;26333:31:0;;;;-1:-1:-1;;;26333:31:0;;;;;;26452:36;;;;;;;;;;-1:-1:-1;26452:36:0;;;;-1:-1:-1;;;26452:36:0;;;;;;25481:35;;;;;;;;;;-1:-1:-1;25481:35:0;;;;;;;;;25973:34;;;;;;;;;;;;;;;;61700:308;;;;;;;;;;-1:-1:-1;61700:308:0;;;;;:::i;:::-;;:::i;25566:75::-;;;;;;;;;;-1:-1:-1;25566:75:0;;;;-1:-1:-1;;;;;25566:75:0;;;44567:1148;27154:6;:13;;-1:-1:-1;;;;27154:13:0;-1:-1:-1;;;27154:13:0;;;;25837:6:::1;44658:19;:17;:19::i;:::-;:24;::::0;44680:2:::1;44658:24;:::i;:::-;:41;;;;:::i;:::-;44638:61;;44731:9;44714:14;:26;44710:128;;;44764:62;::::0;-1:-1:-1;;;44764:62:0;;::::1;::::0;::::1;2572:25:1::0;;;2613:18;;;2606:34;;;2545:18;;44764:62:0::1;;;;;;;;44710:128;44901:11;:21:::0;44876:12:::1;:22:::0;44848:25:::1;::::0;44876:46:::1;::::0;::::1;:::i;:::-;44978:17:::0;;44957:18;;44848:74;;-1:-1:-1;44933:21:0::1;::::0;44957:38:::1;::::0;44978:17;44957:38:::1;:::i;:::-;44933:62:::0;-1:-1:-1;45008:32:0::1;44933:62:::0;45043:34:::1;45060:17:::0;45043:14;:34:::1;:::i;:::-;:50;;;;:::i;:::-;45008:85;;45131:24;45106:11;:21;;;:49;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;45166:17:0;:35;;45187:14;;45166:17;::::1;::::0;:35:::1;::::0;45187:14;;45166:35:::1;:::i;:::-;::::0;;;-1:-1:-1;;45238:16:0::1;::::0;;45252:1:::1;45238:16:::0;;;;;::::1;::::0;;45214:21:::1;::::0;45238:16:::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;45238:16:0::1;45214:40;;45283:4;45265;45270:1;45265:7;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;45265:23:0;;::::1;:7;::::0;;::::1;::::0;;;;;;:23;;;;45309:6:::1;::::0;:13:::1;::::0;;-1:-1:-1;;;45309:13:0;;;;:6;;;::::1;::::0;:11:::1;::::0;:13:::1;::::0;;::::1;::::0;45265:7;;45309:13;;;;;:6;:13:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45299:4;45304:1;45299:7;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;45299:23:0;;::::1;:7;::::0;;::::1;::::0;;;;;:23;45367:6:::1;::::0;45335:56:::1;::::0;45352:4:::1;::::0;45367:6:::1;45376:14:::0;45335:8:::1;:56::i;:::-;45409:81;::::0;;5961:25:1;;;6017:2;6002:18;;5995:34;;;45462:10:0::1;6045:18:1::0;;;6038:60;45474:15:0::1;6129:2:1::0;6114:18;;6107:34;45409:81:0;;::::1;::::0;;;;5948:3:1;45409:81:0;;::::1;45503:6;::::0;45649:17:::1;::::0;45503:204:::1;::::0;-1:-1:-1;;;45503:204:0;;-1:-1:-1;;;;;45503:6:0;;::::1;::::0;:57:::1;::::0;:204:::1;::::0;45575:24;;45503:6:::1;::::0;45630:4;;45649:17;::::1;::::0;45681:15:::1;::::0;45503:204:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;27190:6:0;:14;;-1:-1:-1;;;;27190:14:0;;;-1:-1:-1;;;;;;;;44567:1148:0:o;65258:194::-;65331:4;65367:10;65388:34;65367:10;65407:7;65416:5;65388:8;:34::i;:::-;65440:4;65433:11;;;65258:194;;;;;:::o;51641:525::-;27510:21;:19;:21::i;:::-;51727:15:::1;:13;:15::i;:::-;51775:4;51757:15;:22;51753:100;;;51803:38;::::0;-1:-1:-1;;;51803:38:0;;::::1;::::0;::::1;2572:25:1::0;;;51836:4:0::1;2613:18:1::0;;;2606:34;2545:18;;51803:38:0::1;2398:248:1::0;51753:100:0::1;51863:54;51882:15;51899:7;:17;;;51863:18;:54::i;:::-;51954:7;:17:::0;;51982:35;;;;52028:13;:31;;;52075:83:::1;::::0;;7715:3:1;7697:22;;;7756:1;7735:19;;;7728:30;-1:-1:-1;;;7789:3:1;7774:19;;7767:38;7872:4;7857:20;;7850:36;;;7902:18;;;7895:34;;;52130:10:0::1;-1:-1:-1::0;7945:18:1;;7938:60;52142:15:0::1;-1:-1:-1::0;8014:19:1;;8007:35;52075:83:0::1;::::0;7837:3:1;7822:19;52075:83:0::1;;;;;;;;51716:450;51641:525:::0;:::o;38219:801::-;38351:17;;38315:6;;-1:-1:-1;;;;;38351:17:0;;;;38409:4;38385:29;;;;38381:632;;38438:27;;-1:-1:-1;;;38438:27:0;;;;;;;;;;;38381:632;-1:-1:-1;;;;;38487:26:0;;38483:530;;38534:6;38544:1;38534:11;38530:86;;38579:21;38566:34;;38530:86;-1:-1:-1;;;;;38634:22:0;;:10;:22;38630:107;;38684:37;;-1:-1:-1;;;38684:37:0;;;;;;;;;;;38630:107;38751:38;;-1:-1:-1;;;;;38751:26:0;;;:38;;;;;38778:10;;38751:38;;;;38778:10;38751:26;:38;;;;;;;;;;;;;;;;;;;;;38483:530;;;38826:6;38836:1;38826:11;38822:110;;38871:45;;-1:-1:-1;;;38871:45:0;;38910:4;38871:45;;;3742:51:1;-1:-1:-1;;;;;38871:30:0;;;;;3715:18:1;;38871:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38858:58;;38822:110;38946:55;-1:-1:-1;;;;;38946:33:0;;38980:8;38990:10;38946:33;:55::i;:::-;38283:737;;38219:801;;:::o;65894:247::-;65981:4;66016:10;66037:37;66053:4;66016:10;66068:5;66037:15;:37::i;:::-;66085:26;66095:4;66101:2;66105:5;66085:9;:26::i;:::-;66129:4;66122:11;;;65894:247;;;;;;:::o;56699:337::-;27510:21;:19;:21::i;:::-;-1:-1:-1;;;;;56822:17:0;::::1;;::::0;;;:11:::1;:17;::::0;;;;;56792:48:::1;::::0;56811:9;;56822:17:::1;;56792:18;:48::i;:::-;-1:-1:-1::0;;;;;56868:17:0;::::1;56851:14;56868:17:::0;;;:11:::1;:17;::::0;;;;;;;;;;56896:29;::::1;;-1:-1:-1::0;;56896:29:0;::::1;::::0;::::1;::::0;;;56941:87;;8572:3:1;8554:22;;;8613:2;8592:19;;;8585:31;-1:-1:-1;;;8647:3:1;8632:19;;8625:42;8757:20;;;8750:45;;;;56868:17:0::1;::::0;;::::1;8838:14:1::0;;8831:22;8811:18;;;8804:50;;;;8885:2;8870:18;;8863:50;;;;57000:10:0::1;-1:-1:-1::0;8929:19:1;;8922:44;57012:15:0::1;-1:-1:-1::0;8982:19:1;;8975:35;56868:17:0;56941:87:::1;::::0;8699:3:1;8684:19;56941:87:0::1;;;;;;;;56781:255;56699:337:::0;;:::o;48099:321::-;27510:21;:19;:21::i;:::-;48178:15:::1;:13;:15::i;:::-;48234:11;::::0;48204:42:::1;::::0;48223:9;;-1:-1:-1;;;48234:11:0;::::1;;;48204:18;:42::i;:::-;48274:11;::::0;;48296:23;::::1;;-1:-1:-1::0;;;48296:23:0;;::::1;-1:-1:-1::0;;;;48296:23:0;::::1;;::::0;;;48335:77:::1;::::0;;9323:3:1;9305:22;;;9364:2;9343:19;;;9336:31;-1:-1:-1;;;9398:3:1;9383:19;;9376:42;48274:11:0::1;::::0;;;::::1;::::0;;;::::1;9499:14:1::0;;9492:22;9485:4;9470:20;;9463:52;9531:18;;;9524:50;48384:10:0::1;-1:-1:-1::0;9590:18:1;;9583:60;48396:15:0::1;-1:-1:-1::0;9659:19:1;;9652:35;48335:77:0::1;::::0;9450:3:1;9435:19;48335:77:0::1;9021:672:1::0;53434:657:0;27510:21;:19;:21::i;:::-;-1:-1:-1;;;;;53539:32:0;::::1;;:36:::0;53535:102:::1;;53599:26;;-1:-1:-1::0;;;53599:26:0::1;;;;;;;;;;;53535:102;-1:-1:-1::0;;;;;53651:34:0;::::1;53647:100;;53709:26;::::0;-1:-1:-1;;;53709:26:0;;53732:1:::1;53709:26;::::0;::::1;3742:51:1::0;3715:18;;53709:26:0::1;3596:203:1::0;53647:100:0::1;53757:20;:18;:20::i;:::-;53831:17;::::0;53788:61:::1;::::0;53809:20;;-1:-1:-1;;;;;53831:17:0::1;53788:20;:61::i;:::-;53891:17;::::0;;-1:-1:-1;;;;;;53919:40:0;::::1;-1:-1:-1::0;;;;;53919:40:0;;::::1;::::0;;::::1;::::0;;;53975:108:::1;::::0;;10012:3:1;9994:22;;;10053:2;10032:19;;;10025:31;-1:-1:-1;;;10087:3:1;10072:19;;10065:48;53891:17:0;;;::::1;10218:4:1::0;10203:20;;10196:45;;;10257:18;;;10250:43;54055:10:0::1;-1:-1:-1::0;10309:18:1;;10302:43;54067:15:0::1;-1:-1:-1::0;10361:19:1;;10354:35;53891:17:0;53975:108:::1;::::0;10145:3:1;10130:19;53975:108:0::1;9698:697:1::0;49975:443:0;27510:21;:19;:21::i;:::-;50076:3:::1;50065:8;:14;50061:87;;;50103:33;::::0;-1:-1:-1;;;50103:33:0;;::::1;::::0;::::1;2572:25:1::0;;;50132:3:0::1;2613:18:1::0;;;2606:34;2545:18;;50103:33:0::1;2398:248:1::0;50061:87:0::1;50158:23;:21;:23::i;:::-;50192:44;50211:8;50221:14;;50192:18;:44::i;:::-;50266:14;::::0;;50291:25;;;;50332:78:::1;::::0;;10977:3:1;10959:22;;;11018:2;10997:19;;;10990:31;-1:-1:-1;;;11052:3:1;11037:19;;11030:45;11142:4;11127:20;;11120:36;;;11172:18;;;11165:34;;;50382:10:0::1;-1:-1:-1::0;11215:18:1;;11208:60;50394:15:0::1;-1:-1:-1::0;11284:19:1;;11277:35;50332:78:0::1;::::0;11107:3:1;11092:19;50332:78:0::1;10663:655:1::0;50769:519:0;27510:21;:19;:21::i;:::-;50854:15:::1;:13;:15::i;:::-;50902:4;50884:15;:22;50880:100;;;50930:38;::::0;-1:-1:-1;;;50930:38:0;;::::1;::::0;::::1;2572:25:1::0;;;50963:4:0::1;2613:18:1::0;;;2606:34;2545:18;;50930:38:0::1;2398:248:1::0;50880:100:0::1;50990:53;51009:15;51026:6;:16;;;50990:18;:53::i;:::-;51080:6;:16:::0;;51107:34;;;;51152:12;:30;;;51198:82:::1;::::0;;11637:3:1;11619:22;;;11678:1;11657:19;;;11650:30;-1:-1:-1;;;11711:3:1;11696:19;;11689:37;11793:4;11778:20;;11771:36;;;11823:18;;;11816:34;;;51252:10:0::1;-1:-1:-1::0;11866:18:1;;11859:60;51264:15:0::1;-1:-1:-1::0;11935:19:1;;11928:35;51198:82:0::1;::::0;11758:3:1;11743:19;51198:82:0::1;11323:646:1::0;57384:377:0;27510:21;:19;:21::i;:::-;-1:-1:-1;;;;;57515:25:0;::::1;;::::0;;;:19:::1;:25;::::0;;;;;57485:56:::1;::::0;57504:9;;57515:25:::1;;57485:18;:56::i;:::-;-1:-1:-1::0;;;;;57569:25:0;::::1;57552:14;57569:25:::0;;;:19:::1;:25;::::0;;;;;;;;;;57605:37;::::1;;-1:-1:-1::0;;57605:37:0;::::1;::::0;::::1;::::0;;;57658:95;;12304:3:1;12286:22;;;12345:2;12324:19;;;12317:31;-1:-1:-1;;;12379:3:1;12364:19;;12357:50;12497:20;;;12490:45;;;;57569:25:0::1;::::0;;::::1;12578:14:1::0;;12571:22;12551:18;;;12544:50;;;;12625:2;12610:18;;12603:50;;;;57725:10:0::1;-1:-1:-1::0;12669:19:1;;12662:44;57737:15:0::1;-1:-1:-1::0;12722:19:1;;12715:35;57569:25:0;57658:95:::1;::::0;12439:3:1;12424:19;57658:95:0::1;11974:782:1::0;54509:573:0;27510:21;:19;:21::i;:::-;-1:-1:-1;;;;;54628:16:0;::::1;;::::0;;;:8:::1;:16;::::0;;;;;54598:47:::1;::::0;54617:9;;54628:16:::1;;54598:18;:47::i;:::-;54694:4;-1:-1:-1::0;;;;;54660:39:0::1;54666:6;-1:-1:-1::0;;;;;54660:20:0::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;54660:39:0::1;;;:82;;;;;54737:4;-1:-1:-1::0;;;;;54703:39:0::1;54709:6;-1:-1:-1::0;;;;;54703:20:0::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;54703:39:0::1;;;54660:82;54656:144;;;54766:22;::::0;-1:-1:-1;;;54766:22:0;;-1:-1:-1;;;;;3760:32:1;;54766:22:0::1;::::0;::::1;3742:51:1::0;3715:18;;54766:22:0::1;3596:203:1::0;54656:144:0::1;54824:4;::::0;-1:-1:-1;;;;;54824:4:0::1;54815:14;::::0;;;:8:::1;:14;::::0;;;;;::::1;;54810:80;;54866:4;::::0;-1:-1:-1;;;;;54866:4:0::1;54846:25;::::0;;;:19:::1;:25;::::0;;;;:32;;-1:-1:-1;;54846:32:0::1;54874:4;54846:32;::::0;;54810:80:::1;-1:-1:-1::0;;;;;54917:16:0;::::1;54900:14;54917:16:::0;;;:8:::1;:16;::::0;;;;;;;;;;54944:28;::::1;;-1:-1:-1::0;;54944:28:0;::::1;::::0;::::1;::::0;;;54988:86;;13091:3:1;13073:22;;;13132:1;13111:19;;;13104:30;-1:-1:-1;;;13165:3:1;13150:19;;13143:39;13272:20;;;13265:45;;;;54917:16:0::1;::::0;;::::1;13353:14:1::0;;13346:22;13326:18;;;13319:50;;;;13400:2;13385:18;;13378:50;;;;55046:10:0::1;-1:-1:-1::0;13444:19:1;;13437:44;55058:15:0::1;-1:-1:-1::0;13497:19:1;;13490:35;54917:16:0;54988:86:::1;::::0;13214:3:1;13199:19;54988:86:0::1;12761:770:1::0;23260:103:0;20825:13;:11;:13::i;:::-;23325:30:::1;23352:1;23325:18;:30::i;:::-;23260:103::o:0;47408:408::-;27510:21;:19;:21::i;:::-;25837:6:::1;47506:19;:17;:19::i;:::-;:24;::::0;47528:2:::1;47506:24;:::i;:::-;:41;;;;:::i;:::-;47493:10;:54;47489:118;;;47571:24;::::0;-1:-1:-1;;;47571:24:0;;::::1;::::0;::::1;1901:25:1::0;;;1874:18;;47571:24:0::1;1755:177:1::0;47489:118:0::1;47617:39;47636:10;47648:7;;47617:18;:39::i;:::-;47688:7;::::0;;47706:20;;;;47742:66:::1;::::0;;5961:25:1;;;6017:2;6002:18;;5995:34;;;47780:10:0::1;6045:18:1::0;;;6038:60;;;;47792:15:0::1;6129:2:1::0;6114:18;;6107:34;47742:66:0::1;::::0;5948:3:1;5933:19;47742:66:0::1;5730:417:1::0;48716:369:0;27510:21;:19;:21::i;:::-;48803:23:::1;:21;:23::i;:::-;48867:19;::::0;48837:50:::1;::::0;48856:9;;-1:-1:-1;;;48867:19:0;::::1;;;48837:18;:50::i;:::-;48915:19;::::0;;48945:31;::::1;;-1:-1:-1::0;;;48945:31:0;;::::1;-1:-1:-1::0;;;;48945:31:0;::::1;;::::0;;48992:85:::1;::::0;;13838:3:1;13820:22;;;13858:19;;13851:31;;;;-1:-1:-1;;;13913:3:1;13898:19;;13891:50;48915:19:0::1;::::0;;;::::1;;14022:14:1::0;;14015:22;14008:4;13993:20;;13986:52;14054:18;;;14047:50;49049:10:0::1;-1:-1:-1::0;14113:18:1;;14106:60;49061:15:0::1;-1:-1:-1::0;14182:19:1;;14175:35;48915:19:0;48992:85:::1;::::0;13973:3:1;13958:19;48992:85:0::1;13536:680:1::0;46561:193:0;27510:21;:19;:21::i;:::-;46623:20:::1;:18;:20::i;:::-;46654:16;:23:::0;;-1:-1:-1;;;;46654:23:0::1;-1:-1:-1::0;;;46654:23:0::1;::::0;;46693:53:::1;::::0;;14479:2:1;14461:21;;;14518:2;14498:18;;;14491:30;-1:-1:-1;;;14552:3:1;14537:19;;14530:47;46718:10:0::1;14644:4:1::0;14629:20;;14622:62;46730:15:0::1;14700:18:1::0;;;14693:34;;;;-1:-1:-1;;;;;;;;;;;46693:53:0;14609:3:1;14594:19;46693:53:0::1;;;;;;;;46561:193::o:0;52527:549::-;27510:21;:19;:21::i;:::-;52617:15:::1;:13;:15::i;:::-;52665:4;52647:15;:22;52643:100;;;52693:38;::::0;-1:-1:-1;;;52693:38:0;;::::1;::::0;::::1;2572:25:1::0;;;52726:4:0::1;2613:18:1::0;;;2606:34;2545:18;;52693:38:0::1;2398:248:1::0;52643:100:0::1;52753:58;52772:15;52789:11;:21;;;52753:18;:58::i;:::-;52848:11;:21:::0;;52880:39;;;;52930:17;:35;;;52981:87:::1;::::0;;15052:3:1;15034:22;;;15093:2;15072:19;;;15065:31;-1:-1:-1;;;15127:3:1;15112:19;;15105:42;15214:4;15199:20;;15192:36;;;15244:18;;;15237:34;;;53040:10:0::1;-1:-1:-1::0;15287:18:1;;15280:60;53052:15:0::1;-1:-1:-1::0;15356:19:1;;15349:35;52981:87:0::1;::::0;15179:3:1;15164:19;52981:87:0::1;14738:652:1::0;39678:1118:0;39727:12;;-1:-1:-1;;;39727:12:0;;;;39723:101;;;39783:12;;39797:14;;39763:49;;-1:-1:-1;;;39763:49:0;;-1:-1:-1;;;39783:12:0;;;;;15588:14:1;15581:22;39763:49:0;;;15563:41:1;15620:18;;;15613:34;15536:18;;39763:49:0;15395:258:1;39723:101:0;39871:1;22619:6;-1:-1:-1;;;;;22619:6:0;39852:21;;;;:59;;-1:-1:-1;39901:10:0;39890:7;22592;22619:6;-1:-1:-1;;;;;22619:6:0;;22546:87;39890:7;-1:-1:-1;;;;;39890:21:0;;;39852:59;:114;;;;-1:-1:-1;39951:15:0;39928:20;:10;39941:7;39928:20;:::i;:::-;:38;39852:114;39834:216;;;40000:38;;-1:-1:-1;;;40000:38:0;;40027:10;40000:38;;;3742:51:1;3715:18;;40000:38:0;3596:203:1;39834:216:0;40097:1;22619:6;-1:-1:-1;;;;;22619:6:0;40078:21;:59;;;;-1:-1:-1;40127:10:0;40116:7;22592;22619:6;-1:-1:-1;;;;;22619:6:0;;22546:87;40116:7;-1:-1:-1;;;;;40116:21:0;;;40078:59;:114;;;;-1:-1:-1;40177:15:0;40154:20;:10;40167:7;40154:20;:::i;:::-;:38;40078:114;40060:313;;;40266:20;:10;40279:7;40266:20;:::i;:::-;40331:15;40307:20;:10;40320:7;40307:20;:::i;:::-;40306:40;;;;:::i;:::-;40226:135;;-1:-1:-1;;;40226:135:0;;;;;2572:25:1;;;;2613:18;;;2606:34;2545:18;;40226:135:0;2398:248:1;40060:313:0;40390:19;;-1:-1:-1;;;40390:19:0;;;;40385:79;;40426:19;:26;;-1:-1:-1;;;;40426:26:0;-1:-1:-1;;;40426:26:0;;;40385:79;40479:11;;-1:-1:-1;;;40479:11:0;;;;40474:63;;40507:11;:18;;-1:-1:-1;;;;40507:18:0;-1:-1:-1;;;40507:18:0;;;40474:63;40552:13;;-1:-1:-1;;;40552:13:0;;;;40547:67;;40582:13;:20;;-1:-1:-1;;;;40582:20:0;-1:-1:-1;;;40582:20:0;;;40547:67;40626:12;:19;;-1:-1:-1;;;;40626:19:0;-1:-1:-1;;;40626:19:0;;;40673:15;40656:14;:32;;;40717:12;40699:15;:30;40747:41;;;40760:10;15832:51:1;;15914:2;15899:18;;15892:34;;;;40747:41:0;;15805:18:1;40747:41:0;15658:274:1;49338:305:0;27510:21;:19;:21::i;:::-;49449:13:::1;::::0;49419:44:::1;::::0;49438:9;;-1:-1:-1;;;49449:13:0;::::1;;;49419:18;:44::i;:::-;49491:13;::::0;;49515:25;::::1;;-1:-1:-1::0;;;49515:25:0;;::::1;-1:-1:-1::0;;;;49515:25:0;::::1;;::::0;;;49556:79:::1;::::0;;16239:3:1;16221:22;;;16280:2;16259:19;;;16252:31;-1:-1:-1;;;16314:3:1;16299:19;;16292:44;49491:13:0::1;::::0;;;::::1;::::0;;;::::1;16417:14:1::0;;16410:22;16403:4;16388:20;;16381:52;16449:18;;;16442:50;49607:10:0::1;-1:-1:-1::0;16508:18:1;;16501:60;49619:15:0::1;-1:-1:-1::0;16577:19:1;;16570:35;49556:79:0::1;::::0;16368:3:1;16353:19;49556:79:0::1;15937:674:1::0;41192:151:0;63748:9;:18;;;;41303:6;41242:7;63748:18;;;;;63351:12;;41242:7;;63748:18;41269:42;;63748:18;41269:42;:::i;:::-;:66;;;;:::i;:::-;41262:73;;41192:151;:::o;46930:205::-;27510:21;:19;:21::i;:::-;46995:23:::1;:21;:23::i;:::-;47029:19;:26:::0;;-1:-1:-1;;;;47029:26:0::1;-1:-1:-1::0;;;47029:26:0::1;::::0;;47071:56:::1;::::0;;16874:2:1;16856:21;;;16893:18;;16886:30;;;;-1:-1:-1;;;16947:3:1;16932:19;;16925:50;47099:10:0::1;17042:4:1::0;17027:20;;17020:62;47111:15:0::1;17098:18:1::0;;;17091:34;-1:-1:-1;;;;;;;;;;;47071:56:0;17007:3:1;16992:19;47071:56:0::1;16616:515:1::0;64140:186:0;64209:4;64245:10;64266:30;64245:10;64286:2;64290:5;64266:9;:30::i;45904:166::-;20825:13;:11;:13::i;:::-;45954:15:::1;:13;:15::i;:::-;45980:11;:18:::0;;-1:-1:-1;;;;45980:18:0::1;-1:-1:-1::0;;;45980:18:0::1;::::0;;46014:48:::1;::::0;;17394:2:1;17376:21;;;17433:2;17413:18;;;17406:30;-1:-1:-1;;;17467:3:1;17452:19;;17445:42;46034:10:0::1;17554:4:1::0;17539:20;;17532:62;46046:15:0::1;17610:18:1::0;;;17603:34;;;;-1:-1:-1;;;;;;;;;;;46014:48:0;17519:3:1;17504:19;46014:48:0::1;17136:507:1::0;55548:812:0;27510:21;:19;:21::i;:::-;-1:-1:-1;;;;;55631:23:0;::::1;55627:88;;55678:25;::::0;-1:-1:-1;;;55678:25:0;;-1:-1:-1;;;;;3760:32:1;;55678:25:0::1;::::0;::::1;3742:51:1::0;3715:18;;55678:25:0::1;3596:203:1::0;55627:88:0::1;55765:6;::::0;55725:48:::1;::::0;55746:9;;-1:-1:-1;;;;;55765:6:0::1;55725:20;:48::i;:::-;55814:6;::::0;;-1:-1:-1;;;;;55832:27:0;;::::1;-1:-1:-1::0;;;;;;55832:27:0;::::1;::::0;::::1;::::0;;;55877:63:::1;::::0;;55814:6;;;::::1;17917:34:1::0;;;17982:2;17967:18;;17960:43;;;;55912:10:0::1;18019:18:1::0;;;18012:43;;;;55924:15:0::1;18086:2:1::0;18071:18;;18064:34;55877:63:0::1;::::0;17866:3:1;17851:19;55877:63:0::1;;;;;;;55974:6;::::0;:16:::1;::::0;;-1:-1:-1;;;55974:16:0;;;;56042:1:::1;::::0;-1:-1:-1;;;;;55974:6:0::1;::::0;:14:::1;::::0;:16:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:6;:16:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;55965:34:0::1;;56008:4;56015:6;;;;;;;;;-1:-1:-1::0;;;;;56015:6:0::1;-1:-1:-1::0;;;;;56015:11:0::1;;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;55965:64;::::0;-1:-1:-1;;;;;;55965:64:0::1;::::0;;;;;;-1:-1:-1;;;;;18339:15:1;;;55965:64:0::1;::::0;::::1;18321:34:1::0;18391:15;;18371:18;;;18364:43;18256:18;;55965:64:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;55957:87:0::1;::::0;55953:400:::1;;56077:6;;;;;;;;;-1:-1:-1::0;;;;;56077:6:0::1;-1:-1:-1::0;;;;;56077:14:0::1;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;56068:37:0::1;;56114:4;56121:6;;;;;;;;;-1:-1:-1::0;;;;;56121:6:0::1;-1:-1:-1::0;;;;;56121:11:0::1;;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;56068:67;::::0;-1:-1:-1;;;;;;56068:67:0::1;::::0;;;;;;-1:-1:-1;;;;;18339:15:1;;;56068:67:0::1;::::0;::::1;18321:34:1::0;18391:15;;18371:18;;;18364:43;18256:18;;56068:67:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;56061:4;:74:::0;;-1:-1:-1;;;;;;56061:74:0::1;-1:-1:-1::0;;;;;56061:74:0;;;::::1;::::0;;::::1;::::0;;-1:-1:-1;56157:25:0;;;:19:::1;:25;::::0;;;;;::::1;;56152:99;;56223:4;::::0;-1:-1:-1;;;;;56223:4:0::1;56203:25;::::0;;;:19:::1;:25;::::0;;;;:32;;-1:-1:-1;;56203:32:0::1;56231:4;56203:32;::::0;;56152:99:::1;56279:4;::::0;-1:-1:-1;;;;;56279:4:0::1;56270:14;::::0;;;:8:::1;:14;::::0;;;;;::::1;;56265:77;;56314:4;::::0;-1:-1:-1;;;;;56314:4:0::1;56305:14;::::0;;;:8:::1;:14;::::0;;;;:21;;-1:-1:-1;;56305:21:0::1;56322:4;56305:21;::::0;;56265:77:::1;55616:744;55548:812:::0;:::o;46235:155::-;20825:13;:11;:13::i;:::-;46290:16:::1;:23:::0;;-1:-1:-1;;;;46290:23:0::1;-1:-1:-1::0;;;46290:23:0::1;::::0;;46329:53:::1;::::0;;18676:2:1;18658:21;;;18715:2;18695:18;;;18688:30;-1:-1:-1;;;18749:3:1;18734:19;;18727:47;46354:10:0::1;18841:4:1::0;18826:20;;18819:62;46366:15:0::1;18897:18:1::0;;;18890:34;;;;-1:-1:-1;;;;;;;;;;;46329:53:0;18806:3:1;18791:19;46329:53:0::1;18418:512:1::0;61700:308:0;20825:13;:11;:13::i;:::-;-1:-1:-1;;;;;;;61786:27:0;::::1;::::0;61782:91:::1;;61837:24;::::0;-1:-1:-1;;;61837:24:0;;-1:-1:-1;;;;;3760:32:1;;61837:24:0::1;::::0;::::1;3742:51:1::0;3715:18;;61837:24:0::1;3596:203:1::0;61782:91:0::1;61883:39;61904:8;61914:7;22592::::0;22619:6;-1:-1:-1;;;;;22619:6:0;;22546:87;61914:7:::1;61883:20;:39::i;:::-;61933:12;:23:::0;;-1:-1:-1;;;;;;61933:23:0::1;-1:-1:-1::0;;;;;61933:23:0;::::1;;::::0;;61967:33:::1;61933:23:::0;61967::::1;:33::i;:::-;61700:308:::0;:::o;72766:136::-;72854:40;72863:8;72873:7;72882:5;72889:4;72854:8;:40::i;:::-;72766:136;;;:::o;41548:223::-;41604:20;:18;:20::i;:::-;41639:12;;-1:-1:-1;;;;;41639:12:0;41655:10;41639:26;;;;:51;;-1:-1:-1;41680:10:0;41669:7;22592;22619:6;-1:-1:-1;;;;;22619:6:0;;22546:87;41669:7;-1:-1:-1;;;;;41669:21:0;;;41639:51;41635:129;;;41714:38;;-1:-1:-1;;;41714:38:0;;41741:10;41714:38;;;3742:51:1;3715:18;;41714:38:0;3596:203:1;43415:121:0;43469:11;;-1:-1:-1;;;43469:11:0;;;;43465:64;;;43504:13;;-1:-1:-1;;;43504:13:0;;19137:2:1;43504:13:0;;;19119:21:1;19176:1;19156:18;;;19149:29;-1:-1:-1;;;19194:18:1;;;19187:33;19237:18;;43504:13:0;18935:326:1;41902:185:0;42006:7;41994:8;:19;41990:90;;42037:31;;-1:-1:-1;;;42037:31:0;;;;;1901:25:1;;;1874:18;;42037:31:0;1755:177:1;5824:162:0;5934:43;;;-1:-1:-1;;;;;15850:32:1;;5934:43:0;;;15832:51:1;15899:18;;;;15892:34;;;5934:43:0;;;;;;;;;;15805:18:1;;;;5934:43:0;;;;;;;;-1:-1:-1;;;;;5934:43:0;-1:-1:-1;;;5934:43:0;;;5907:71;;5927:5;;5907:19;:71::i;74686:496::-;-1:-1:-1;;;;;64818:21:0;;;74789:24;64818:21;;;:11;:21;;;;;;;;:30;;;;;;;;;;-1:-1:-1;;74859:37:0;;74855:320;;74936:5;74917:16;:24;74913:132;;;74969:60;;-1:-1:-1;;;74969:60:0;;-1:-1:-1;;;;;19486:32:1;;74969:60:0;;;19468:51:1;19535:18;;;19528:34;;;19578:18;;;19571:34;;;19441:18;;74969:60:0;19266:345:1;74913:132:0;75088:60;75097:8;75107:7;75135:5;75116:16;:24;75142:5;75088:8;:60::i;67421:1245::-;-1:-1:-1;;;;;67505:18:0;;67501:88;;67547:30;;-1:-1:-1;;;67547:30:0;;67574:1;67547:30;;;3742:51:1;3715:18;;67547:30:0;3596:203:1;67501:88:0;-1:-1:-1;;;;;67603:16:0;;67599:88;;67643:32;;-1:-1:-1;;;67643:32:0;;67672:1;67643:32;;;3742:51:1;3715:18;;67643:32:0;3596:203:1;67599:88:0;67702:12;;-1:-1:-1;;;67702:12:0;;;;67697:151;;-1:-1:-1;;;;;67736:17:0;;;;;;:11;:17;;;;;;;;67735:18;:38;;;;-1:-1:-1;;;;;;67758:15:0;;;;;;:11;:15;;;;;;;;67757:16;67735:38;67731:106;;;67801:20;;-1:-1:-1;;;67801:20:0;;;;;;;;;;;67731:106;67864:6;;-1:-1:-1;;;67864:6:0;;;;;:27;;-1:-1:-1;;;;;;67874:17:0;;;;;;:11;:17;;;;;;;;67864:27;67860:91;;;67915:24;67923:4;67929:2;67933:5;67915:7;:24::i;67860:91::-;67973:4;;-1:-1:-1;;;;;67965:12:0;;;67973:4;;67965:12;;;;:29;;-1:-1:-1;67981:13:0;;-1:-1:-1;;;67981:13:0;;;;67965:29;:82;;;;-1:-1:-1;68040:7:0;;68019:17;;67998:18;;:38;;68019:17;67998:38;:::i;:::-;:49;;67965:82;:121;;;;-1:-1:-1;68079:7:0;;68069:4;63721:7;63748:18;;;:9;:18;;;;;;68051:35;;67965:121;67961:475;;;68124:7;;68152:16;;-1:-1:-1;;;68152:16:0;;;;:41;;;;-1:-1:-1;68191:1:0;22619:6;-1:-1:-1;;;;;22619:6:0;68172:21;68152:41;68148:238;;;68214:22;25837:6;68239:19;:17;:19::i;:::-;:24;;68261:2;68239:24;:::i;:::-;:41;;;;:::i;:::-;68214:66;;68330:10;68312:14;:28;;:58;;68360:10;68312:58;;;68343:14;68312:58;68299:71;;68195:191;68148:238;68402:22;68413:10;68402;:22::i;:::-;68088:348;67961:475;68489:11;;68467:5;;-1:-1:-1;;;68489:11:0;;;;:33;;;;-1:-1:-1;;;;;;68505:17:0;;;;;;:11;:17;;;;;;;;68504:18;68489:33;:53;;;;-1:-1:-1;;;;;;68527:15:0;;;;;;:11;:15;;;;;;;;68526:16;68489:53;68485:134;;;68570:37;68591:4;68597:2;68601:5;68570:20;:37::i;:::-;68559:48;;68485:134;68631:27;68639:4;68645:2;68649:8;68631:7;:27::i;42218:179::-;42316:7;42304:19;;:8;:19;;;42300:90;;42347:31;;-1:-1:-1;;;42347:31:0;;1408:14:1;;1401:22;42347:31:0;;;1383:41:1;1356:18;;42347:31:0;1243:187:1;43147:136:0;43206:16;;-1:-1:-1;;;43206:16:0;;;;43202:74;;;43246:18;;-1:-1:-1;;;43246:18:0;;19818:2:1;43246:18:0;;;19800:21:1;19857:1;19837:18;;;19830:29;-1:-1:-1;;;19875:18:1;;;19868:38;19923:18;;43246::0;19616:331:1;42532:195:0;42642:7;-1:-1:-1;;;;;42628:21:0;:10;-1:-1:-1;;;;;42628:21:0;;42624:96;;42673:35;;-1:-1:-1;;;42673:35:0;;-1:-1:-1;;;;;3760:32:1;;42673:35:0;;;3742:51:1;3715:18;;42673:35:0;3596:203:1;43686:145:0;43748:19;;-1:-1:-1;;;43748:19:0;;;;43744:80;;;43791:21;;-1:-1:-1;;;43791:21:0;;20154:2:1;43791:21:0;;;20136::1;20193:2;20173:18;;;20166:30;-1:-1:-1;;;20212:18:1;;;20205:41;20263:18;;43791:21:0;19952:335:1;22825:162:0;22896:10;22885:7;22592;22619:6;-1:-1:-1;;;;;22619:6:0;;22546:87;22885:7;-1:-1:-1;;;;;22885:21:0;;22881:99;;22930:38;;-1:-1:-1;;;22930:38:0;;22957:10;22930:38;;;3742:51:1;3715:18;;22930:38:0;3596:203:1;24340:191:0;24414:16;24433:6;;-1:-1:-1;;;;;24450:17:0;;;-1:-1:-1;;;;;;24450:17:0;;;;;;24483:40;;24433:6;;;;;;;24483:40;;24414:16;24483:40;24403:128;24340:191;:::o;42869:136::-;42928:16;;-1:-1:-1;;;42928:16:0;;;;42924:74;;;42968:18;;-1:-1:-1;;;42968:18:0;;20494:2:1;42968:18:0;;;20476:21:1;20533:1;20513:18;;;20506:29;-1:-1:-1;;;20551:18:1;;;20544:38;20599:18;;42968::0;20292:331:1;23789:220:0;20825:13;:11;:13::i;:::-;-1:-1:-1;;;;;23874:22:0;::::1;23870:93;;23920:31;::::0;-1:-1:-1;;;23920:31:0;;23948:1:::1;23920:31;::::0;::::1;3742:51:1::0;3715:18;;23920:31:0::1;3596:203:1::0;23870:93:0::1;23973:28;23992:8;23973:18;:28::i;73673:455::-:0;-1:-1:-1;;;;;73789:22:0;;73785:94;;73835:32;;-1:-1:-1;;;73835:32:0;;73864:1;73835:32;;;3742:51:1;3715:18;;73835:32:0;3596:203:1;73785:94:0;-1:-1:-1;;;;;73893:21:0;;73889:92;;73938:31;;-1:-1:-1;;;73938:31:0;;73966:1;73938:31;;;3742:51:1;3715:18;;73938:31:0;3596:203:1;73889:92:0;-1:-1:-1;;;;;73991:21:0;;;;;;;:11;:21;;;;;;;;:30;;;;;;;;;:38;;;74040:81;;;;74094:7;-1:-1:-1;;;;;74075:34:0;74084:8;-1:-1:-1;;;;;74075:34:0;;74103:5;74075:34;;;;1901:25:1;;1889:2;1874:18;;1755:177;74075:34:0;;;;;;;;73673:455;;;;:::o;6376:295::-;6457:23;6483:33;-1:-1:-1;;;;;6483:27:0;;6511:4;6483:27;:33::i;:::-;6457:59;;6531:10;:17;6552:1;6531:22;;:57;;;;;6569:10;6558:30;;;;;;;;;;;;:::i;:::-;6557:31;6531:57;6527:137;;;6612:40;;-1:-1:-1;;;6612:40:0;;-1:-1:-1;;;;;3760:32:1;;6612:40:0;;;3742:51:1;3715:18;;6612:40:0;3596:203:1;70470:999:0;-1:-1:-1;;;;;63748:18:0;;70556;63748;;;:9;:18;;;;;;70577:21;;70593:5;;70577:21;:::i;:::-;70556:42;;70609:13;25837:6;70647:14;;70625:19;:17;:19::i;:::-;:36;;;;:::i;:::-;:53;;;;:::i;:::-;70609:69;;70708:5;70695:10;:18;:46;;;;-1:-1:-1;;;;;;70718:23:0;;;;;;:19;:23;;;;;;;;70717:24;70695:46;70691:122;;;70765:36;;-1:-1:-1;;;70765:36:0;;;;;2572:25:1;;;2613:18;;;2606:34;;;2545:18;;70765:36:0;2398:248:1;70691:122:0;-1:-1:-1;;;;;70829:18:0;;70825:369;;70880:5;70864:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;70825:369:0;;-1:-1:-1;70825:369:0;;-1:-1:-1;;;;;70940:15:0;;70918:19;70940:15;;;:9;:15;;;;;;70974:19;;;70970:117;;;71021:50;;-1:-1:-1;;;71021:50:0;;-1:-1:-1;;;;;19486:32:1;;71021:50:0;;;19468:51:1;19535:18;;;19528:34;;;19578:18;;;19571:34;;;19441:18;;71021:50:0;19266:345:1;70970:117:0;-1:-1:-1;;;;;71130:15:0;;;;;;:9;:15;;;;;71148:19;;;;71130:37;;70825:369;-1:-1:-1;;;;;71210:16:0;;71206:213;;71272:12;:21;;;;;;;71206:213;;;-1:-1:-1;;;;;71370:13:0;;;;;;:9;:13;;;;;:22;;;;;;71206:213;71451:2;-1:-1:-1;;;;;71436:25:0;71445:4;-1:-1:-1;;;;;71436:25:0;;71455:5;71436:25;;;;1901::1;;1889:2;1874:18;;1755:177;71436:25:0;;;;;;;;70545:924;;70470:999;;;:::o;69263:518::-;27154:6;:13;;-1:-1:-1;;;;27154:13:0;-1:-1:-1;;;27154:13:0;;;-1:-1:-1;;;;;69394:14:0;::::1;69370:7:::0;69394:14;;;:8:::1;:14;::::0;;;;;27154:13;69394:14:::1;:40:::0;::::1;;;-1:-1:-1::0;69413:6:0::1;:16:::0;:20;;69394:40:::1;69390:104;;;69458:24;69469:4;69475:6;69458:10;:24::i;:::-;69451:31;;;;69390:104;-1:-1:-1::0;;;;;69508:12:0;::::1;;::::0;;;:8:::1;:12;::::0;;;;;::::1;;:39:::0;::::1;;;-1:-1:-1::0;69525:7:0::1;:17:::0;:21;;69508:39:::1;69504:104;;;69571:25;69583:4;69589:6;69571:11;:25::i;69504:104::-;-1:-1:-1::0;;;;;69623:14:0;::::1;;::::0;;;:8:::1;:14;::::0;;;;;::::1;;69622:15;:32:::0;::::1;;;-1:-1:-1::0;;;;;;69642:12:0;::::1;;::::0;;;:8:::1;:12;::::0;;;;;::::1;;69641:13;69622:32;:63;;;;-1:-1:-1::0;69659:11:0::1;:21:::0;:25;;69622:63:::1;69618:132;;;69709:29;69725:4;69731:6;69709:15;:29::i;69618:132::-;-1:-1:-1::0;69767:6:0;27178:1:::1;27190:6:::0;:14;;-1:-1:-1;;;;27190:14:0;;;69263:518;;-1:-1:-1;;;69263:518:0:o;1635:178::-;1735:12;1767:38;1789:6;1797:4;1803:1;1767:21;:38::i;58117:141::-;27154:6;:13;;-1:-1:-1;;;;27154:13:0;-1:-1:-1;;;27154:13:0;;;58221:29:::1;::::0;;;;::::1;::::0;;;27163:4;58221:29;;;;;::::1;::::0;::::1;::::0;58194:7;;58221:29:::1;::::0;58237:4;58243:6;58221:7:::1;:29::i;58598:143::-:0;27154:6;:13;;-1:-1:-1;;;;27154:13:0;-1:-1:-1;;;27154:13:0;;;58703:30:::1;::::0;;;;::::1;::::0;;;58711:7:::1;58703:30:::0;;;;;::::1;::::0;::::1;::::0;58676:7;;58703:30:::1;::::0;58720:4;58726:6;58703:7:::1;:30::i;59085:151::-:0;27154:6;:13;;-1:-1:-1;;;;27154:13:0;-1:-1:-1;;;27154:13:0;;;59194:34:::1;::::0;;;;::::1;::::0;;;59202:11:::1;59194:34:::0;;;;;::::1;::::0;::::1;::::0;59167:7;;59194:34:::1;::::0;59215:4;59221:6;59194:7:::1;:34::i;2406:456::-:0;2539:12;2592:5;2568:21;:29;2564:110;;;2621:41;;-1:-1:-1;;;2621:41:0;;2656:4;2621:41;;;3742:51:1;3715:18;;2621:41:0;3596:203:1;2564:110:0;2685:12;2699:23;2726:6;-1:-1:-1;;;;;2726:11:0;2745:5;2766:4;2726:55;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2684:97;;;;2799:55;2826:6;2834:7;2843:10;2799:26;:55::i;:::-;2792:62;2406:456;-1:-1:-1;;;;;;2406:456:0:o;59632:492::-;27154:6;:13;;-1:-1:-1;;;;27154:13:0;-1:-1:-1;;;27154:13:0;;;59765:17;;59813:15:::1;::::0;59726:7;;59765:17;59813:19:::1;::::0;59726:7;59813:19:::1;:::i;:::-;59797:12;:35;59793:83;;-1:-1:-1::0;59860:4:0::1;59793:83;59886:17;25837:6;59906:17;59915:8:::0;59906:6;:17:::1;:::i;:::-;:34;;;;:::i;:::-;59886:54:::0;-1:-1:-1;59951:17:0::1;59971:18;59886:54:::0;59971:6;:18:::1;:::i;:::-;59951:38:::0;-1:-1:-1;60004:13:0;;60000:90:::1;;60034:44;60043:7;60052:4;60058:9;60069:8;60034;:44::i;:::-;27190:6:::0;:14;;-1:-1:-1;;;;27190:14:0;;;60107:9;59632:492;-1:-1:-1;;;;;;59632:492:0:o;3626:425::-;3774:12;3804:7;3799:245;;3828:19;3836:10;3828:7;:19::i;:::-;3799:245;;;3884:17;;:22;:49;;;;-1:-1:-1;;;;;;3910:18:0;;;:23;3884:49;3880:121;;;3961:24;;-1:-1:-1;;;3961:24:0;;-1:-1:-1;;;;;3760:32:1;;3961:24:0;;;3742:51:1;3715:18;;3961:24:0;3596:203:1;3880:121:0;-1:-1:-1;4022:10:0;4015:17;;60512:278;27154:6;:13;;-1:-1:-1;;;;27154:13:0;-1:-1:-1;;;27154:13:0;;;60658:17;;27154:13;;60678:3;;60649:26:::1;::::0;:6;:26:::1;:::i;:::-;:32;;;;:::i;:::-;60622:59;;60692:41;60708:16;60726:6;60692:15;:41::i;:::-;60746:36;60754:4;60768;60775:6;60746:7;:36::i;:::-;-1:-1:-1::0;;27190:6:0;:14;;-1:-1:-1;;;;27190:14:0;;;-1:-1:-1;;;60512:278:0:o;4319:328::-;4389:17;;:21;4385:255;;4484:10;4478:17;4541:15;4528:10;4524:2;4520:19;4513:44;4385:255;4611:17;;-1:-1:-1;;;4611:17:0;;;;;;;;;;;61045:185;27154:6;:13;;-1:-1:-1;;;;27154:13:0;-1:-1:-1;;;27154:13:0;;;61141:12:::1;:42:::0;;61167:16;;61141:12;27154:13;;61141:42:::1;::::0;61167:16;;61141:42:::1;:::i;:::-;::::0;;;-1:-1:-1;;61194:18:0;:28;;61216:6;;61194:18;::::1;::::0;:28:::1;::::0;61216:6;;61194:28:::1;:::i;:::-;::::0;;;-1:-1:-1;;27190:6:0;:14;;-1:-1:-1;;;;27190:14:0;;;-1:-1:-1;;61045:185:0:o;14:180:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:1;;14:180;-1:-1:-1;14:180:1:o;199:250::-;284:1;294:113;308:6;305:1;302:13;294:113;;;384:11;;;378:18;365:11;;;358:39;330:2;323:10;294:113;;;-1:-1:-1;;441:1:1;423:16;;416:27;199:250::o;454:396::-;603:2;592:9;585:21;566:4;635:6;629:13;678:6;673:2;662:9;658:18;651:34;694:79;766:6;761:2;750:9;746:18;741:2;733:6;729:15;694:79;:::i;:::-;834:2;813:15;-1:-1:-1;;809:29:1;794:45;;;;841:2;790:54;;454:396;-1:-1:-1;;454:396:1:o;855:131::-;-1:-1:-1;;;;;930:31:1;;920:42;;910:70;;976:1;973;966:12;991:247;1050:6;1103:2;1091:9;1082:7;1078:23;1074:32;1071:52;;;1119:1;1116;1109:12;1071:52;1158:9;1145:23;1177:31;1202:5;1177:31;:::i;1435:315::-;1503:6;1511;1564:2;1552:9;1543:7;1539:23;1535:32;1532:52;;;1580:1;1577;1570:12;1532:52;1619:9;1606:23;1638:31;1663:5;1638:31;:::i;:::-;1688:5;1740:2;1725:18;;;;1712:32;;-1:-1:-1;;;1435:315:1:o;1937:456::-;2014:6;2022;2030;2083:2;2071:9;2062:7;2058:23;2054:32;2051:52;;;2099:1;2096;2089:12;2051:52;2138:9;2125:23;2157:31;2182:5;2157:31;:::i;:::-;2207:5;-1:-1:-1;2264:2:1;2249:18;;2236:32;2277:33;2236:32;2277:33;:::i;:::-;1937:456;;2329:7;;-1:-1:-1;;;2383:2:1;2368:18;;;;2355:32;;1937:456::o;2840:118::-;2926:5;2919:13;2912:21;2905:5;2902:32;2892:60;;2948:1;2945;2938:12;2963:382;3028:6;3036;3089:2;3077:9;3068:7;3064:23;3060:32;3057:52;;;3105:1;3102;3095:12;3057:52;3144:9;3131:23;3163:31;3188:5;3163:31;:::i;:::-;3213:5;-1:-1:-1;3270:2:1;3255:18;;3242:32;3283:30;3242:32;3283:30;:::i;:::-;3332:7;3322:17;;;2963:382;;;;;:::o;3350:241::-;3406:6;3459:2;3447:9;3438:7;3434:23;3430:32;3427:52;;;3475:1;3472;3465:12;3427:52;3514:9;3501:23;3533:28;3555:5;3533:28;:::i;3804:388::-;3872:6;3880;3933:2;3921:9;3912:7;3908:23;3904:32;3901:52;;;3949:1;3946;3939:12;3901:52;3988:9;3975:23;4007:31;4032:5;4007:31;:::i;:::-;4057:5;-1:-1:-1;4114:2:1;4099:18;;4086:32;4127:33;4086:32;4127:33;:::i;4420:127::-;4481:10;4476:3;4472:20;4469:1;4462:31;4512:4;4509:1;4502:15;4536:4;4533:1;4526:15;4552:168;4625:9;;;4656;;4673:15;;;4667:22;;4653:37;4643:71;;4694:18;;:::i;4725:217::-;4765:1;4791;4781:132;;4835:10;4830:3;4826:20;4823:1;4816:31;4870:4;4867:1;4860:15;4898:4;4895:1;4888:15;4781:132;-1:-1:-1;4927:9:1;;4725:217::o;4947:128::-;5014:9;;;5035:11;;;5032:37;;;5049:18;;:::i;5080:125::-;5145:9;;;5166:10;;;5163:36;;;5179:18;;:::i;5342:127::-;5403:10;5398:3;5394:20;5391:1;5384:31;5434:4;5431:1;5424:15;5458:4;5455:1;5448:15;5474:251;5544:6;5597:2;5585:9;5576:7;5572:23;5568:32;5565:52;;;5613:1;5610;5603:12;5565:52;5645:9;5639:16;5664:31;5689:5;5664:31;:::i;6152:980::-;6414:4;6462:3;6451:9;6447:19;6493:6;6482:9;6475:25;6519:2;6557:6;6552:2;6541:9;6537:18;6530:34;6600:3;6595:2;6584:9;6580:18;6573:31;6624:6;6659;6653:13;6690:6;6682;6675:22;6728:3;6717:9;6713:19;6706:26;;6767:2;6759:6;6755:15;6741:29;;6788:1;6798:195;6812:6;6809:1;6806:13;6798:195;;;6877:13;;-1:-1:-1;;;;;6873:39:1;6861:52;;6968:15;;;;6933:12;;;;6909:1;6827:9;6798:195;;;-1:-1:-1;;;;;;;7049:32:1;;;;7044:2;7029:18;;7022:60;-1:-1:-1;;;7113:3:1;7098:19;7091:35;7010:3;6152:980;-1:-1:-1;;;6152:980:1:o;8053:184::-;8123:6;8176:2;8164:9;8155:7;8151:23;8147:32;8144:52;;;8192:1;8189;8182:12;8144:52;-1:-1:-1;8215:16:1;;8053:184;-1:-1:-1;8053:184:1:o;20628:245::-;20695:6;20748:2;20736:9;20727:7;20723:23;20719:32;20716:52;;;20764:1;20761;20754:12;20716:52;20796:9;20790:16;20815:28;20837:5;20815:28;:::i;20878:287::-;21007:3;21045:6;21039:13;21061:66;21120:6;21115:3;21108:4;21100:6;21096:17;21061:66;:::i;:::-;21143:16;;;;;20878:287;-1:-1:-1;;20878:287:1:o

Swarm Source

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