ETH Price: $3,431.87 (+5.69%)
Gas: 6 Gwei

Token

CherryPYE (CHERRYPYE)
 

Overview

Max Total Supply

38,754.802491097263218884 CHERRYPYE

Holders

129

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

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

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

Contract Source Code Verified (Exact Match)

Contract Name:
CHERRY

Compiler Version
v0.8.1+commit.df193b15

Optimization Enabled:
Yes with 999 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-05-25
*/

// File: contracts-eth/interfaces/IBEP20.sol



pragma solidity >=0.4.0;

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

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

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

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

    /**
     * @dev Returns the bep token owner.
     */
    function getOwner() external view returns (address);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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



pragma solidity ^0.8.0;

interface IPYESwapRouter01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

// File: contracts-eth/interfaces/IPYESwapRouter.sol



pragma solidity >=0.6.2;


interface IPYESwapRouter is IPYESwapRouter01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function pairFeeAddress(address pair) external view returns (address);
    function adminFee() external view returns (uint256);
    function feeAddressGet() external view returns (address);
}

// File: contracts-eth/interfaces/IPYESwapPair.sol



pragma solidity >=0.5.0;

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

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

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

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

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

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

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

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

    function initialize(address, address) external;
    function setBaseToken(address _baseToken) external;
}

// File: contracts-eth/interfaces/IPYESwapFactory.sol



pragma solidity >=0.5.0;

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

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

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

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

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
    function routerInitialize(address) external;
    function routerAddress() external view returns (address);
}

// File: contracts-eth/interfaces/IWETH.sol



pragma solidity >=0.5.0;

interface IWETH {
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);
    function deposit() external payable;
    function transfer(address to, uint value) external returns (bool);
    function withdraw(uint) external;
}

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


// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

// File: @openzeppelin/contracts/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

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

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

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

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


// OpenZeppelin Contracts v4.4.1 (utils/Arrays.sol)

pragma solidity ^0.8.0;


/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
    /**
     * @dev Searches a sorted `array` and returns the first index that contains
     * a value greater or equal to `element`. If no such index exists (i.e. all
     * values in the array are strictly less than `element`), the array length is
     * returned. Time complexity O(log n).
     *
     * `array` is expected to be sorted in ascending order, and to contain no
     * repeated elements.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        if (array.length == 0) {
            return 0;
        }

        uint256 low = 0;
        uint256 high = array.length;

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds down (it does integer division with truncation).
            if (array[mid] > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && array[low - 1] == element) {
            return low - 1;
        } else {
            return low;
        }
    }
}

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


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

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol


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

pragma solidity ^0.8.0;


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

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

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

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


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

pragma solidity ^0.8.0;

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

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


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

pragma solidity ^0.8.0;


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

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


// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

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

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


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

pragma solidity ^0.8.0;




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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

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

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;





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

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

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

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

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

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

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

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

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

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

        _revokeRole(role, account);
    }

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

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

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: contracts-eth/libs/BEP20.sol



pragma solidity >=0.4.0;






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

    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

    /**
     * @dev Returns the bep token owner.
     */
    function getOwner() external override view returns (address) {
        return owner();
    }

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

    /**
     * @dev Returns the token decimals.
     */
    function decimals() public override view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev Returns the token symbol.
     */
    function symbol() public override view returns (string memory) {
        return _symbol;
    }

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

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

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

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

    /**
     * @dev See {BEP20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {BEP20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {BEP20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public override virtual returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(
            sender,
            _msgSender(),
            _allowances[sender][_msgSender()].sub(amount, 'BEP20: transfer amount exceeds allowance')
        );
        return true;
    }

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

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {BEP20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(
            _msgSender(),
            spender,
            _allowances[_msgSender()][spender].sub(subtractedValue, 'BEP20: decreased allowance below zero')
        );
        return true;
    }

    /**
     * @dev Creates `amount` tokens and assigns them to `msg.sender`, increasing
     * the total supply.
     *
     * Requirements
     *
     * - `msg.sender` must be the token owner
     */
    function mint(uint256 amount) public onlyOwner returns (bool) {
        _mint(_msgSender(), amount);
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal {
        require(sender != address(0), 'BEP20: transfer from the zero address');
        require(recipient != address(0), 'BEP20: transfer to the zero address');

        _balances[sender] = _balances[sender].sub(amount, 'BEP20: transfer amount exceeds balance');
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

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

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

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

        _balances[account] = _balances[account].sub(amount, 'BEP20: burn amount exceeds balance');
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

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

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

    /**
     * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(
            account,
            _msgSender(),
            _allowances[account][_msgSender()].sub(amount, 'BEP20: burn amount exceeds allowance')
        );
    }
}
// File: contracts-eth/Cherry2.sol


pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;















contract CHERRY is Context, Ownable, AccessControl, ERC20 {
    using SafeMath for uint256;
    using Address for address;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
    bytes32 public constant FEE_SETTER_ROLE = keccak256("FEE_SETTER_ROLE");

    // staked struct	
    struct Staked {	
        uint256 amount;	
    }	
    address[] holders;	
    mapping (address => uint256) holderIndexes;	
    uint256 public totalStaked;

    // Fees
    // Add and remove fee types and destinations here as needed
    struct Fees {
        uint256 developmentFee;
        uint256 buybackFee;
        uint256 burnFee;
        address developmentAddress;
    }

    // Transaction fee values
    // Add and remove fee value types here as needed
    struct FeeValues {
        uint256 transferAmount;
        uint256 development;
        uint256 buyback;
        uint256 burn;
    }

    // Token details
    mapping (address => uint256) _balances;
    mapping (address => mapping (address => uint256)) private _allowances;
    mapping (address => Staked) public staked;

    // blacklist and staking contract mappings	
    mapping (address => bool) isBlacklisted; 	
    mapping (address => bool) isStakingContract; 

    // Set total supply here
    uint256 private _tTotal;
    uint256 private constant MAX_SUPPLY = 100000000 * 10**18;

    // auto set buyback to false. additional buyback params. blockPeriod acts as a time delay in the shouldAutoBuyback(). Last uint represents last block for buyback occurance.
    struct Settings {
        bool autoBuybackEnabled;
        uint256 autoBuybackCap;
        uint256 autoBuybackAccumulator;
        uint256 autoBuybackAmount;
        uint256 autoBuybackBlockPeriod;
        uint256 autoBuybackBlockLast;
        uint256 minimumBuyBackThreshold;
    }

    // Users states
    mapping (address => bool) private _isExcludedFromFee;

    // Outside Swap Pairs
    mapping (address => bool) private _includeSwapFee;


    // Pair Details
    mapping (uint256 => address) private pairs;
    mapping (uint256 => address) private tokens;
    uint256 private pairsLength;
    mapping (address => bool) public _isPairAddress;


    // Set the name, symbol, and decimals here
    string constant _name = "CherryPYE";
    string constant _symbol = "CHERRYPYE";
    uint8 constant _decimals = 18;

    Fees public _defaultFees;
    Fees public _defaultSellFees;
    Fees private _previousFees;
    Fees private _emptyFees;
    Fees private _sellFees;
    Fees private _outsideBuyFees;
    Fees private _outsideSellFees;

    Settings public _buyback;

    IPYESwapRouter public pyeSwapRouter;
    address public pyeSwapPair;
    address public WETH;
    address public constant _burnAddress = 0x000000000000000000000000000000000000dEaD;

    bool public swapEnabled = true;
    bool inSwap;

    modifier swapping() { inSwap = true; _; inSwap = false; }
    modifier onlyExchange() {
        bool isPair = false;
        for(uint i = 0; i < pairsLength; i++) {
            if(pairs[i] == msg.sender) isPair = true;
        }
        require(
            msg.sender == address(pyeSwapRouter)
            || isPair
            , "PYE: NOT_ALLOWED"
        );
        _;
    }

    /// @dev A record of each accounts delegate
    mapping (address => address) public delegates;

    /// @notice A checkpoint for marking number of votes from a given block
    struct Checkpoint {
        uint32 fromBlock;
        uint256 votes;
    }

    /// @notice A record of votes checkpoints for each account, by index
    mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;

    /// @notice The number of checkpoints for each account
    mapping (address => uint32) public numCheckpoints;

    /// @notice The EIP-712 typehash for the contract's domain
    bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");

    /// @notice The EIP-712 typehash for the delegation struct used by the contract
    bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    /// @notice A record of states for signing / validating signatures
    mapping (address => uint) public nonces;

    /// @notice An event thats emitted when an account changes its delegate
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /// @notice An event thats emitted when a delegate account's vote balance changes
    event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);

    // Edit the constructor in order to declare default fees on deployment
    constructor (address _router, address _development, uint256 _developmentFee, uint256 _buybackFee, uint256 _burnFee) ERC20("","") {
        _setupRole(MINTER_ROLE, msg.sender);
        _setupRole(BURNER_ROLE, msg.sender);
        _setupRole(FEE_SETTER_ROLE, msg.sender);
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);

        pyeSwapRouter = IPYESwapRouter(_router);
        WETH = pyeSwapRouter.WETH();
        pyeSwapPair = IPYESwapFactory(pyeSwapRouter.factory())
        .createPair(address(this), WETH, true);

        tokens[pairsLength] = WETH;
        pairs[pairsLength] = pyeSwapPair;
        pairsLength += 1;
        _isPairAddress[pyeSwapPair] = true;

        _isExcludedFromFee[_msgSender()] = true;
        _isExcludedFromFee[pyeSwapPair] = true;
        _isExcludedFromFee[address(this)] = true;
        _isExcludedFromFee[_burnAddress] = true;

        // This should match the struct Fee
        _defaultFees = Fees(
            _developmentFee,
            _buybackFee,
            0,
            _development
        );

        _defaultSellFees = Fees(
            _developmentFee,
            _buybackFee,
            _burnFee,
            _development
        );

        _sellFees = Fees(
            0,
            0,
            _burnFee,
            _development
        );

        _outsideBuyFees = Fees(
            _developmentFee.add(_buybackFee),
            0,
            0,
            _development
        );

        _outsideSellFees = Fees(
            _developmentFee.add(_buybackFee),
            0,
            _burnFee,
            _development
        );

        IPYESwapPair(pyeSwapPair).updateTotalFee(400);
        
        emit Transfer(address(0), _msgSender(), _tTotal);
    }

    function name() public pure override returns (string memory) {
        return _name;
    }

    function symbol() public pure override returns (string memory) {
        return _symbol;
    }

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

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

    function maxSupply() public pure returns (uint256) {
        return MAX_SUPPLY;
    }

    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance"));
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual override returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual override returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "BEP20: decreased allowance below zero"));
        return true;
    }

    function excludeFromFee(address account) public {
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        _isExcludedFromFee[account] = true;
    }

    function includeInFee(address account) public {
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        _isExcludedFromFee[account] = false;
    }

    function addOutsideSwapPair(address account) public {
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        _includeSwapFee[account] = true;
    }

    function removeOutsideSwapPair(address account) public {
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        _includeSwapFee[account] = false;
    }

    function _updatePairsFee() internal {
        for (uint j = 0; j < pairsLength; j++) {
            IPYESwapPair(pairs[j]).updateTotalFee(getTotalFee());
        }
    }


    // Functions to update fees and addresses 

    function setBuybackPercent(uint256 _buybackFee) external {
        require(hasRole(FEE_SETTER_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        require(_defaultSellFees.developmentFee.add(_defaultSellFees.burnFee).add(_buybackFee) <= 2500, "Fees exceed max limit.");
        _defaultFees.buybackFee = _buybackFee;
        _defaultSellFees.buybackFee = _buybackFee;
        _outsideBuyFees.developmentFee = _outsideBuyFees.developmentFee.add(_buybackFee);
        _outsideSellFees.developmentFee = _outsideSellFees.developmentFee.add(_buybackFee);
        _updatePairsFee();
    }

    function setDevelopmentPercent(uint256 _developmentFee) external {
        require(hasRole(FEE_SETTER_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        require(_defaultSellFees.buybackFee.add(_defaultSellFees.burnFee).add(_developmentFee) <= 2500, "Fees exceed max limit.");
        _defaultFees.developmentFee = _developmentFee;
        _defaultSellFees.developmentFee = _developmentFee;
        _outsideBuyFees.developmentFee = _outsideBuyFees.buybackFee.add(_developmentFee);
        _outsideSellFees.developmentFee = _outsideSellFees.buybackFee.add(_developmentFee);
        _updatePairsFee();
    }

    function setdevelopmentAddress(address _development) external {
        require(hasRole(FEE_SETTER_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        require(_development != address(0), "PYE: Address Zero is not allowed");
        _defaultFees.developmentAddress = _development;
        _defaultSellFees.developmentAddress = _development;
        _outsideBuyFees.developmentAddress = _development;
        _outsideSellFees.developmentAddress = _development;
    }

    function setSellBurnFee(uint256 _burnFee) external {
        require(hasRole(FEE_SETTER_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        require(_defaultSellFees.buybackFee.add(_defaultSellFees.developmentFee).add(_burnFee) <= 2500, "Fees exceed max limit.");
        _sellFees.burnFee = _burnFee;
        _defaultSellFees.burnFee = _burnFee;
        _outsideSellFees.burnFee = _burnFee;
    }



    function updateRouterAndPair(address _router, address _pair) public {
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        _isExcludedFromFee[pyeSwapPair] = false;
        pyeSwapRouter = IPYESwapRouter(_router);
        pyeSwapPair = _pair;
        WETH = pyeSwapRouter.WETH();

        _isPairAddress[pyeSwapPair] = true;
        _isExcludedFromFee[pyeSwapPair] = true;

        pairs[0] = pyeSwapPair;
        tokens[0] = WETH;

        IPYESwapPair(pyeSwapPair).updateTotalFee(getTotalFee());
    }

    //to receive ETH from pyeRouter when swapping
    receive() external payable {}

    function _getValues(uint256 tAmount) private view returns (FeeValues memory) {
        FeeValues memory values = FeeValues(
            0,
            calculateFee(tAmount, _defaultFees.developmentFee),
            calculateFee(tAmount, _defaultFees.buybackFee),
            calculateFee(tAmount, _defaultFees.burnFee)
        );

        values.transferAmount = tAmount.sub(values.development).sub(values.buyback).sub(values.burn);
        return values;
    }

    function calculateFee(uint256 _amount, uint256 _fee) private pure returns (uint256) {
        if(_fee == 0) return 0;
        return _amount.mul(_fee).div(
            10**4
        );
    }

    function removeAllFee() private {
        _previousFees = _defaultFees;
        _defaultFees = _emptyFees;
    }

    function setSellFee() private {
        _previousFees = _defaultFees;
        _defaultFees = _sellFees;
    }

    function setOutsideBuyFee() private {
        _previousFees = _defaultFees;
        _defaultFees = _outsideBuyFees;
    }

    function setOutsideSellFee() private {
        _previousFees = _defaultFees;
        _defaultFees = _outsideSellFees;
    }

    function restoreAllFee() private {
        _defaultFees = _previousFees;
    }

    function isExcludedFromFee(address account) public view returns(bool) {
        return _isExcludedFromFee[account];
    }

    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) override internal {
        require(owner != address(0), "BEP20: approve from the zero address");
        require(spender != address(0), "BEP20: approve to the zero address");

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

    function getBalance(address keeper) public view returns (uint256){
        return _balances[keeper];
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) override internal {
        require(from != address(0), "BEP20: transfer from the zero address");
        require(to != address(0), "BEP20: transfer to the zero address");
        require(amount > 0, "Transfer amount must be greater than zero");
        require(!isBlacklisted[to]);
        _beforeTokenTransfer(from, to, amount);

        if(shouldAutoBuyback(amount)){ triggerAutoBuyback(); }

        if(isStakingContract[to]) { 	
            uint256 newAmountAdd = staked[from].amount.add(amount);	
            setStaked(from, newAmountAdd);	
        }	
        if(isStakingContract[from]) {	
            uint256 newAmountSub = staked[to].amount.sub(amount);	
            setStaked(to, newAmountSub);	
        }

        //indicates if fee should be deducted from transfer of tokens
        uint8 takeFee = 0;
        if(_isPairAddress[to] && from != address(pyeSwapRouter) && !isExcludedFromFee(from)) {
            takeFee = 1;
        } else if(_includeSwapFee[from]) {
            takeFee = 2;
        } else if(_includeSwapFee[to]) {
            takeFee = 3;
        }

        //transfer amount, it will take tax
        _tokenTransfer(from, to, amount, takeFee);
    }

    function getCirculatingSupply() public view returns (uint256) {
        return _tTotal.sub(balanceOf(_burnAddress)).sub(balanceOf(address(0)));
    }

    function getTotalFee() public view returns (uint256) {
        return _defaultFees.developmentFee
            .add(_defaultFees.buybackFee)
            .add(_defaultFees.burnFee);
    }

    //this method is responsible for taking all fee, if takeFee is true
    function _tokenTransfer(address sender, address recipient, uint256 amount, uint8 takeFee) private {
        if(takeFee == 0) {
            removeAllFee();
        } else if(takeFee == 1) {
            setSellFee();
        } else if(takeFee == 2) {
            setOutsideBuyFee();
        } else if(takeFee == 3) {
            setOutsideSellFee();
        }

        FeeValues memory _values = _getValues(amount);
        _balances[sender] = _balances[sender].sub(amount, "Insufficient Balance");
        _balances[recipient] = _balances[recipient].add(_values.transferAmount);
        _takeFees(_values);

        emit Transfer(sender, recipient, _values.transferAmount);

        if(delegates[sender] == address(0)) {
            delegates[sender] = sender;
        }

        if(delegates[recipient] == address(0)) {
            delegates[recipient] = recipient;
        }

        if(amount == _values.transferAmount) {	
            _moveDelegates(delegates[sender], delegates[recipient], amount);	
        } else {	
            _moveDelegates(delegates[sender], delegates[recipient], _values.transferAmount);	
            _moveDelegates(delegates[sender], delegates[_defaultFees.developmentAddress], _values.development);	
            _moveDelegates(delegates[sender], address(0), _values.burn);	
        }

        if(takeFee == 0 || takeFee == 1) {
            restoreAllFee();
        } else if(takeFee == 2 || takeFee == 3) {
            restoreAllFee();
            emit Transfer(sender, _defaultFees.developmentAddress, _values.development);
        }
    }

    function _takeFees(FeeValues memory values) private {
        _takeFee(values.development, _defaultFees.developmentAddress);
        _takeBurnFee(values.burn);
    }

    function _takeFee(uint256 tAmount, address recipient) private {
        if(recipient == address(0)) return;
        if(tAmount == 0) return;

        _balances[recipient] = _balances[recipient].add(tAmount);
    }

    function _takeBurnFee(uint256 amount) private {
        if(amount == 0) return;

        _balances[address(this)] = _balances[address(this)].add(amount);
        _burn(address(this), amount);
    }

    // This function transfers the fees to the correct addresses. 
    function depositLPFee(uint256 amount, address token) public onlyExchange {
        uint256 tokenIndex = _getTokenIndex(token);
        if(tokenIndex < pairsLength) {
            uint256 allowanceT = IERC20(token).allowance(msg.sender, address(this));
            if(allowanceT >= amount) {
                IERC20(token).transferFrom(msg.sender, address(this), amount);

                if(token != WETH) {
                    uint256 balanceBefore = IERC20(address(WETH)).balanceOf(address(this));
                    swapToWETH(amount, token);
                    uint256 fAmount = IERC20(address(WETH)).balanceOf(address(this)).sub(balanceBefore);
                    
                    // All fees to be declared here in order to be calculated and sent
                    uint256 totalFee = getTotalFee();
                    uint256 developmentFeeAmount = fAmount.mul(_defaultFees.developmentFee).div(totalFee);

                    IERC20(WETH).transfer(_defaultFees.developmentAddress, developmentFeeAmount);
                } else {
                    // All fees to be declared here in order to be calculated and sent
                    uint256 totalFee = getTotalFee();
                    uint256 developmentFeeAmount = amount.mul(_defaultFees.developmentFee).div(totalFee);

                    IERC20(token).transfer(_defaultFees.developmentAddress, developmentFeeAmount);
                }
            }
        }
    }

    function swapToWETH(uint256 amount, address token) internal {
        address[] memory path = new address[](2);
        path[0] = token;
        path[1] = WETH;

        IERC20(token).approve(address(pyeSwapRouter), amount);
        pyeSwapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            amount,
            0,
            path,
            address(this),
            block.timestamp
        );
    }

    // runs check to see if autobuyback should trigger
    function shouldAutoBuyback(uint256 amount) internal view returns (bool) {
        return msg.sender != pyeSwapPair
        && !inSwap
        && _buyback.autoBuybackEnabled
        && _buyback.autoBuybackBlockLast + _buyback.autoBuybackBlockPeriod <= block.number // After N blocks from last buyback
        && IERC20(address(WETH)).balanceOf(address(this)) >= _buyback.autoBuybackAmount
        && amount >= _buyback.minimumBuyBackThreshold;
    }

    // triggers auto buyback
    function triggerAutoBuyback() internal {
        buyTokens(_buyback.autoBuybackAmount, _burnAddress);
        _buyback.autoBuybackBlockLast = block.number;
        _buyback.autoBuybackAccumulator = _buyback.autoBuybackAccumulator.add(_buyback.autoBuybackAmount);
        if(_buyback.autoBuybackAccumulator > _buyback.autoBuybackCap){ _buyback.autoBuybackEnabled = false; }
    }

    // logic to purchase moonforce tokens
    function buyTokens(uint256 amount, address to) internal swapping {
        address[] memory path = new address[](2);
        path[0] = WETH;
        path[1] = address(this);

        IERC20(WETH).approve(address(pyeSwapRouter), amount);
        pyeSwapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            amount,
            0,
            path,
            to,
            block.timestamp
        );
    }

    // manually adjust the buyback settings to suit your needs
    function setAutoBuybackSettings(bool _enabled, uint256 _cap, uint256 _amount, uint256 _period, uint256 _minimumThreshold) external {
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        _buyback.autoBuybackEnabled = _enabled;
        _buyback.autoBuybackCap = _cap;
        _buyback.autoBuybackAccumulator = 0;
        _buyback.autoBuybackAmount = _amount;
        _buyback.autoBuybackBlockPeriod = _period;
        _buyback.autoBuybackBlockLast = block.number;
        _buyback.minimumBuyBackThreshold = _minimumThreshold;
    }

    function _getTokenIndex(address _token) internal view returns (uint256) {
        uint256 index = pairsLength + 1;
        for(uint256 i = 0; i < pairsLength; i++) {
            if(tokens[i] == _token) index = i;
        }

        return index;
    }

    function addPair(address _pair, address _token) public {
        address factory = pyeSwapRouter.factory();
        require(
            msg.sender == factory
            || msg.sender == address(pyeSwapRouter)
            || msg.sender == address(this)
        , "PYE: NOT_ALLOWED"
        );

        if(!_checkPairRegistered(_pair)) {
            _isExcludedFromFee[_pair] = true;
            _isPairAddress[_pair] = true;

            pairs[pairsLength] = _pair;
            tokens[pairsLength] = _token;

            pairsLength += 1;

            IPYESwapPair(_pair).updateTotalFee(getTotalFee());
        }
    }

    function _checkPairRegistered(address _pair) internal view returns (bool) {
        bool isPair = false;
        for(uint i = 0; i < pairsLength; i++) {
            if(pairs[i] == _pair) isPair = true;
        }

        return isPair;
    }

    // Rescue eth that is sent here by mistake
    function rescueETH(uint256 amount, address to) external {
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        payable(to).transfer(amount);
      }

    // Rescue tokens that are sent here by mistake
    function rescueToken(IERC20 token, uint256 amount, address to) external {
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        if( token.balanceOf(address(this)) < amount ) {
            amount = token.balanceOf(address(this));
        }
        token.transfer(to, amount);
    }

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


    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) override internal {
        require(account != address(0), 'BEP20: mint to the zero address');
        
        _tTotal = _tTotal.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) override internal {	
        require(account != address(0), 'BEP20: burn from the zero address');	
        _balances[account] = _balances[account].sub(amount, 'BEP20: burn amount exceeds balance');	
        _tTotal = _tTotal.sub(amount);	
        emit Transfer(account, address(0), amount);	
    }

    function burn(uint256 _amount) public {	
        require(hasRole(BURNER_ROLE, msg.sender), "FUEL: NOT_ALLOWED");	
        _beforeTokenTransfer(msg.sender, address(0), _amount);
        _burn(msg.sender, _amount);	
        if(delegates[msg.sender] == address(0)) {	
            delegates[msg.sender] = msg.sender;	
        }	
        _moveDelegates(delegates[msg.sender], address(0), _amount);	
    }
    	
    function burnFrom(address _from, uint256 _amount) public {	
        require(hasRole(BURNER_ROLE, msg.sender), "APPLE: NOT_ALLOWED");	
        _spendAllowance(_from, msg.sender, _amount);
        _beforeTokenTransfer(_from, address(0), _amount);	
        _burn(_from, _amount);	
        if(delegates[_from] == address(0)) {	
            delegates[_from] = _from;	
        }	
        _moveDelegates(delegates[_from], address(0), _amount);	
    }

    /// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef).
    function mint(address _to, uint256 _amount) public {
        require(hasRole(MINTER_ROLE, msg.sender), "CHERRY: NOT_ALLOWED");
        require(totalSupply().add(_amount) <= MAX_SUPPLY, "CHERRY: REACHED_MAX_SUPPLY");
        _beforeTokenTransfer(address(0), _to, _amount);
        _mint(_to, _amount);
        
        if(delegates[_to] == address(0)) {
            delegates[_to] = _to;
        }
        _moveDelegates(address(0), delegates[_to], _amount);
    }

    
    // Copied and modified from YAM code:
    // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol
    // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol
    // Which is copied and modified from COMPOUND:
    // https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol

    /**
     * @notice Delegate votes from `msg.sender` to `delegatee`
    * @param delegatee The address to delegate votes to
    */
    function delegate(address delegatee) external {
        return _delegate(msg.sender, delegatee);
    }

    /**
     * @notice Delegates votes from signatory to `delegatee`
     * @param delegatee The address to delegate votes to
     * @param nonce The contract state required to match the signature
     * @param expiry The time at which to expire the signature
     * @param v The recovery byte of the signature
     * @param r Half of the ECDSA signature pair
     * @param s Half of the ECDSA signature pair
     */
    function delegateBySig(
        address delegatee,
        uint nonce,
        uint expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    )
    external
    {
        bytes32 domainSeparator = keccak256(
            abi.encode(
                DOMAIN_TYPEHASH,
                keccak256(bytes(name())),
                getChainId(),
                address(this)
            )
        );

        bytes32 structHash = keccak256(
            abi.encode(
                DELEGATION_TYPEHASH,
                delegatee,
                nonce,
                expiry
            )
        );

        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                domainSeparator,
                structHash
            )
        );

        address signatory = ecrecover(digest, v, r, s);
        require(signatory != address(0), "CHERRY::delegateBySig: invalid signature");
        require(nonce == nonces[signatory]++, "CHERRY::delegateBySig: invalid nonce");
        require(block.timestamp <= expiry, "CHERRY::delegateBySig: signature expired");
        return _delegate(signatory, delegatee);
    }

    /**
     * @notice Gets the current votes balance for `account`
     * @param account The address to get votes balance
     * @return The number of current votes for `account`
     */
    function getCurrentVotes(address account)
    external
    view
    returns (uint256)
    {
        uint32 nCheckpoints = numCheckpoints[account];
        return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
    }

    /**
     * @notice Determine the prior number of votes for an account as of a block number
     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
     * @param account The address of the account to check
     * @param blockNumber The block number to get the vote balance at
     * @return The number of votes the account had as of the given block
     */
    function getPriorVotes(address account, uint blockNumber)
    external
    view
    returns (uint256)
    {
        require(blockNumber < block.number, "CHERRY::getPriorVotes: not yet determined");

        uint32 nCheckpoints = numCheckpoints[account];
        if (nCheckpoints == 0) {
            return 0;
        }

        // First check most recent balance
        if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
            return checkpoints[account][nCheckpoints - 1].votes;
        }

        // Next check implicit zero balance
        if (checkpoints[account][0].fromBlock > blockNumber) {
            return 0;
        }

        uint32 lower = 0;
        uint32 upper = nCheckpoints - 1;
        while (upper > lower) {
            uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
            Checkpoint memory cp = checkpoints[account][center];
            if (cp.fromBlock == blockNumber) {
                return cp.votes;
            } else if (cp.fromBlock < blockNumber) {
                lower = center;
            } else {
                upper = center - 1;
            }
        }
        return checkpoints[account][lower].votes;
    }

    function _delegate(address delegator, address delegatee)
    internal
    {
        address currentDelegate = delegates[delegator];
        uint256 delegatorBalance = balanceOf(delegator); // balance of underlying CHERRY (not scaled);
        delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);

        _moveDelegates(currentDelegate, delegatee, delegatorBalance);
    }

    function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
        if (srcRep != dstRep && amount > 0) {
            if (srcRep != address(0)) {
                // decrease old representative
                uint32 srcRepNum = numCheckpoints[srcRep];
                uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
                uint256 srcRepNew = srcRepOld.sub(amount);
                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
            }

            if (dstRep != address(0)) {
                // increase new representative
                uint32 dstRepNum = numCheckpoints[dstRep];
                uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
                uint256 dstRepNew = dstRepOld.add(amount);
                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
            }
        }
    }

    function _writeCheckpoint(
        address delegatee,
        uint32 nCheckpoints,
        uint256 oldVotes,
        uint256 newVotes
    )
    internal
    {
        uint32 blockNumber = safe32(block.number, "CHERRY::_writeCheckpoint: block number exceeds 32 bits");

        if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
            checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
        } else {
            checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
            numCheckpoints[delegatee] = nCheckpoints + 1;
        }

        emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
    }

    function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
        require(n < 2**32, errorMessage);
        return uint32(n);
    }

    function getChainId() internal view returns (uint) {
        uint256 chainId;
        assembly { chainId := chainid() }
        return chainId;
    }

    //-------------------- BEGIN STAKED FXNS ------------------------------	
    function getOwnedBalance(address account) external view returns (uint256){	
        return staked[account].amount.add(_balances[account]);	
    }	
    function setStaked(address holder, uint256 amount) internal  {	
        if(amount > 0 && staked[holder].amount == 0){	
            addHolder(holder);	
        }else if(amount == 0 && staked[holder].amount > 0){	
            removeHolder(holder);	
        }	
        totalStaked = totalStaked.sub(staked[holder].amount).add(amount);	
        staked[holder].amount = amount;	
    }	
    function addHolder(address holder) internal {	
        holderIndexes[holder] = holders.length;	
        holders.push(holder);	
    }	
    function removeHolder(address holder) internal {	
        holders[holderIndexes[holder]] = holders[holders.length-1];	
        holderIndexes[holders[holders.length-1]] = holderIndexes[holder];	
        holders.pop();	
    }	
    // set an address as a staking contract	
    function setIsStakingContract(address account, bool set) external {	
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "FUEL: NOT_ALLOWED");	
        isStakingContract[account] = set;	
    }	
    //--------------------------------------BEGIN BLACKLIST FUNCTIONS---------|	
    // enter an address to blacklist it. This blocks transfers TO that address. Balcklisted members can still sell.	
    function blacklistAddress(address addressToBlacklist) external {	
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "FUEL: NOT_ALLOWED");	
        require(!isBlacklisted[addressToBlacklist] , "Address is already blacklisted!");	
        isBlacklisted[addressToBlacklist] = true;	
    }	
    // enter a currently blacklisted address to un-blacklist it.	
    function removeFromBlacklist(address addressToRemove) external {	
        require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "FUEL: NOT_ALLOWED");	
        require(isBlacklisted[addressToRemove] , "Address has not been blacklisted! Enter an address that is on the blacklist.");	
        isBlacklisted[addressToRemove] = false;	
    }

    // -------------------------------------BEGIN MODIFIED SNAPSHOT FUNCTIONS--------------------|

    //@ dev a direct, modified implementation of ERC20 snapshot designed to track totalOwnedBalance (the sum of balanceOf(acct) and staked.amount of that acct), as opposed
    // to just balanceOf(acct). totalSupply is tracked normally via _tTotal in the totalSupply() function.

    using Arrays for uint256[];
    using Counters for Counters.Counter;
    Counters.Counter private _currentSnapshotId;

    struct Snapshots {
        uint256[] ids;
        uint256[] values;
    }

    mapping(address => Snapshots) private _accountBalanceSnapshots;
    Snapshots private _totalSupplySnapshots;
    event Snapshot(uint256 id);

    // owner can manually call a snapshot.
    function snapshot() public onlyOwner {
        _snapshot();
    }

    function _snapshot() internal virtual returns (uint256) {
        _currentSnapshotId.increment();

        uint256 currentId = _getCurrentSnapshotId();
        emit Snapshot(currentId);
        return currentId;
    }

    function _getCurrentSnapshotId() internal view virtual returns (uint256) {
        return _currentSnapshotId.current();
    }

    function getCurrentSnapshotID() public view onlyOwner returns (uint256) {
        return _getCurrentSnapshotId();
    }

    // modified to also read users staked balance. 
    function totalBalanceOfAt(address account, uint256 snapshotId) public view virtual returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);

        return snapshotted ? value : (balanceOf(account).add(staked[account].amount));
    }

    function totalSupplyAt(uint256 snapshotId) public view virtual returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);

        return snapshotted ? value : totalSupply();
    }

    function _valueAt(uint256 snapshotId, Snapshots storage snapshots) private view returns (bool, uint256) {
        require(snapshotId > 0, "ERC20Snapshot: id is 0");
        require(snapshotId <= _getCurrentSnapshotId(), "ERC20Snapshot: nonexistent id");

        uint256 index = snapshots.ids.findUpperBound(snapshotId);

        if (index == snapshots.ids.length) {
            return (false, 0);
        } else {
            return (true, snapshots.values[index]);
        }
    }

    // modified to also add staked[acct].amount
    function _updateAccountSnapshot(address account) private {
        _updateSnapshot(_accountBalanceSnapshots[account], (balanceOf(account).add(staked[account].amount)));
    }

    function _updateTotalSupplySnapshot() private {
        _updateSnapshot(_totalSupplySnapshots, totalSupply());
    }

    function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
        uint256 currentId = _getCurrentSnapshotId();
        if (_lastSnapshotId(snapshots.ids) < currentId) {
            snapshots.ids.push(currentId);
            snapshots.values.push(currentValue);
        }
    }

    function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) {
        if (ids.length == 0) {
            return 0;
        } else {
            return ids[ids.length - 1];
        }
    }

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

        if (from == address(0)) {
            // mint
            _updateAccountSnapshot(to);
            _updateTotalSupplySnapshot();
        } else if (to == address(0)) {
            // burn
            _updateAccountSnapshot(from);
            _updateTotalSupplySnapshot();
        } else {
            // transfer
            _updateAccountSnapshot(from);
            _updateAccountSnapshot(to);
        }
    }

}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_development","type":"address"},{"internalType":"uint256","name":"_developmentFee","type":"uint256"},{"internalType":"uint256","name":"_buybackFee","type":"uint256"},{"internalType":"uint256","name":"_burnFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Snapshot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BURNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_SETTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_burnAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_buyback","outputs":[{"internalType":"bool","name":"autoBuybackEnabled","type":"bool"},{"internalType":"uint256","name":"autoBuybackCap","type":"uint256"},{"internalType":"uint256","name":"autoBuybackAccumulator","type":"uint256"},{"internalType":"uint256","name":"autoBuybackAmount","type":"uint256"},{"internalType":"uint256","name":"autoBuybackBlockPeriod","type":"uint256"},{"internalType":"uint256","name":"autoBuybackBlockLast","type":"uint256"},{"internalType":"uint256","name":"minimumBuyBackThreshold","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_defaultFees","outputs":[{"internalType":"uint256","name":"developmentFee","type":"uint256"},{"internalType":"uint256","name":"buybackFee","type":"uint256"},{"internalType":"uint256","name":"burnFee","type":"uint256"},{"internalType":"address","name":"developmentAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_defaultSellFees","outputs":[{"internalType":"uint256","name":"developmentFee","type":"uint256"},{"internalType":"uint256","name":"buybackFee","type":"uint256"},{"internalType":"uint256","name":"burnFee","type":"uint256"},{"internalType":"address","name":"developmentAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_isPairAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addOutsideSwapPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"addPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addressToBlacklist","type":"address"}],"name":"blacklistAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint256","name":"votes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"depositLPFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"excludeFromFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"keeper","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCirculatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentSnapshotID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getCurrentVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getOwnedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPriorVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"includeInFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pyeSwapPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pyeSwapRouter","outputs":[{"internalType":"contract IPYESwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addressToRemove","type":"address"}],"name":"removeFromBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeOutsideSwapPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"},{"internalType":"uint256","name":"_cap","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_period","type":"uint256"},{"internalType":"uint256","name":"_minimumThreshold","type":"uint256"}],"name":"setAutoBuybackSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_buybackFee","type":"uint256"}],"name":"setBuybackPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_developmentFee","type":"uint256"}],"name":"setDevelopmentPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"set","type":"bool"}],"name":"setIsStakingContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_burnFee","type":"uint256"}],"name":"setSellBurnFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_development","type":"address"}],"name":"setdevelopmentAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"snapshot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"staked","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"totalBalanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_pair","type":"address"}],"name":"updateRouterAndPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052603b805460ff60a01b1916600160a01b1790553480156200002457600080fd5b50604051620064dd380380620064dd8339810160408190526200004791620008c4565b604080516020808201835260008083528351918201909352918252906200007762000071620006b3565b620006b7565b81516200008c906005906020850190620007e4565b508051620000a2906006906020840190620007e4565b505050620000d77f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200070760201b60201c565b620001037f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a8483362000707565b6200012f7fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f881820603362000707565b6200013c60003362000707565b603980546001600160a01b0319166001600160a01b038781169190911791829055604080516315ab88c960e31b81529051929091169163ad5c464891600480820192602092909190829003018186803b1580156200019957600080fd5b505afa158015620001ae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001d49190620008a7565b603b80546001600160a01b0319166001600160a01b039283161790556039546040805163c45a015560e01b81529051919092169163c45a0155916004808301926020929190829003018186803b1580156200022e57600080fd5b505afa15801562000243573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002699190620008a7565b603b546040516320b7f73960e21b81526001600160a01b03928316926382dfdce492620002a29230929091169060019060040162000938565b602060405180830381600087803b158015620002bd57600080fd5b505af1158015620002d2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f89190620008a7565b603a80546001600160a01b039283166001600160a01b0319918216178255603b5460148054600090815260136020908152604080832080548716958916959095179094559454825482526012909552918220805490931693909416929092179055815460019291906200036d90849062000965565b9091555050603a546001600160a01b03166000908152601560205260408120805460ff1916600190811790915590601090620003a8620006b3565b6001600160a01b03908116825260208083019390935260409182016000908120805495151560ff19968716179055603a548216815260108452828120805486166001908117909155308252838220805487168217905561dead82527f9e93e1db4a1f807cc22b2aecf4deeb0bf5745f1ecb319e87c68c5624c0fa6b698054909616179094558151608080820184528882528185018890528184018690529189166060918201819052601689905560178890556018869055601980546001600160a01b03199081168317909155845180850186528a81528087018a90528086018990528301829052601a8a9055601b899055601c889055601d805482168317905584518085018652878152808701889052808601899052909201819052602686905560279590955560288690556029805490911690941790935580519283019052819062000502908690869062002c7062000717821b17901c565b8152600060208083018290526040808401929092526001600160a01b038881166060948501528451602a5584820151602b5584830151602c559390920151602d80546001600160a01b0319169190941617909255815160808101909252819062000579908690869062000717811b62002c7017901c565b8152600060208083019190915260408083018590526001600160a01b038881166060948501528451602e5591840151602f55838101516030559290910151603180546001600160a01b031916918316919091179055603a5491516334cae58160e21b815291169063d32b960490620005f890610190906004016200095c565b602060405180830381600087803b1580156200061357600080fd5b505af115801562000628573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200064e919062000916565b5062000659620006b3565b6001600160a01b031660006001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600f54604051620006a091906200095c565b60405180910390a35050505050620009c7565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6200071382826200072c565b5050565b600062000725828462000965565b9392505050565b620007388282620007b9565b620007135760008281526001602081815260408084206001600160a01b0386168552909152909120805460ff1916909117905562000775620006b3565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b828054620007f2906200098a565b90600052602060002090601f01602090048101928262000816576000855562000861565b82601f106200083157805160ff191683800117855562000861565b8280016001018555821562000861579182015b828111156200086157825182559160200191906001019062000844565b506200086f92915062000873565b5090565b5b808211156200086f576000815560010162000874565b80516001600160a01b0381168114620008a257600080fd5b919050565b600060208284031215620008b9578081fd5b62000725826200088a565b600080600080600060a08688031215620008dc578081fd5b620008e7866200088a565b9450620008f7602087016200088a565b6040870151606088015160809098015196999198509695945092505050565b60006020828403121562000928578081fd5b8151801515811462000725578182fd5b6001600160a01b039384168152919092166020820152901515604082015260600190565b90815260200190565b600082198211156200098557634e487b7160e01b81526011600452602481fd5b500190565b6002810460018216806200099f57607f821691505b60208210811415620009c157634e487b7160e01b600052602260045260246000fd5b50919050565b615b0680620009d76000396000f3fe6080604052600436106104f05760003560e01c806379cc679011610294578063b4b5ea571161015e578063dfd66cb3116100d6578063f1127ed81161008a578063f3290d751161006f578063f3290d7514610d68578063f8a67a6214610d88578063f8b2cb4f14610925576104f7565b8063f1127ed814610d1a578063f2fde38b14610d48576104f7565b8063e7a324dc116100bb578063e7a324dc14610cd0578063e934768314610ce5578063ea2f0b3714610cfa576104f7565b8063dfd66cb314610c9b578063e284db3e14610cb0576104f7565b8063c80bbbeb1161012d578063d547741f11610112578063d547741f14610c46578063d5abeb0114610c66578063dd62ed3e14610c7b576104f7565b8063c80bbbeb14610c1c578063d539139314610c31576104f7565b8063b4b5ea5714610ba7578063b6f3e08714610bc7578063bd3900c014610be7578063c3cda52014610bfc576104f7565b80639711715a1161020c578063a457c2d7116101c0578063ad5c4648116101a5578063ad5c464814610b52578063af2f6dd814610b67578063b0a863f914610b87576104f7565b8063a457c2d714610b12578063a9059cbb14610b32576104f7565b806398807d84116101f157806398807d8414610abd578063a0558c3f14610add578063a217fddf14610afd576104f7565b80639711715a14610a88578063981b24d014610a9d576104f7565b80638283bbf3116102635780638da5cb5b116102485780638da5cb5b14610a3e57806391d1485414610a5357806395d89b4114610a73576104f7565b80638283bbf314610a0957806382ccff8914610a29576104f7565b806379cc67901461099f5780637ae316d0146109bf5780637ecebe00146109d4578063817b1cd2146109f4576104f7565b80633bf33976116103d55780635c19a95c1161034d5780636fcfff4511610301578063715018a6116102e6578063715018a614610945578063782d6fe11461095a5780637891b5101461097a576104f7565b80636fcfff45146108f857806370a0823114610925576104f7565b80636baa9a57116103325780636baa9a57146108a35780636ddd1713146108c35780636ed52e68146108d8576104f7565b80635c19a95c1461086357806367243ea814610883576104f7565b806342966c68116103a45780635342acb4116103895780635342acb414610803578063537df3b614610823578063587cde1e14610843576104f7565b806342966c68146107c3578063437823ec146107e3576104f7565b80633bf33976146107435780633d8a62d31461076357806340b28c2f1461078357806340c10f19146107a3576104f7565b8063248a9ca3116104685780632f2ff15d11610437578063313ce5671161041c578063313ce567146106e157806336568abe146107035780633950935114610723576104f7565b80632f2ff15d146106a157806330367554146106c1576104f7565b8063248a9ca31461062f578063282c51f31461064f5780632b112e49146106645780632c77735c14610679576104f7565b8063174ca3ec116104bf5780631973dc37116104a45780631973dc37146105da57806320606b70146105fa57806323b872dd1461060f576104f7565b8063174ca3ec1461059657806318160ddd146105b8576104f7565b806301ffc9a7146104fc57806302e8e85f1461053257806306fdde0314610554578063095ea7b314610576576104f7565b366104f757005b600080fd5b34801561050857600080fd5b5061051c610517366004614d72565b610da8565b6040516105299190614f3f565b60405180910390f35b34801561053e57600080fd5b50610547610e06565b6040516105299190614ed4565b34801561056057600080fd5b50610569610e15565b6040516105299190614feb565b34801561058257600080fd5b5061051c610591366004614c17565b610e4c565b3480156105a257600080fd5b506105b66105b1366004614cf3565b610e6a565b005b3480156105c457600080fd5b506105cd610ec6565b6040516105299190614f7c565b3480156105e657600080fd5b506105b66105f5366004614d36565b610ecc565b34801561060657600080fd5b506105cd610f85565b34801561061b57600080fd5b5061051c61062a366004614baa565b610fa9565b34801561063b57600080fd5b506105cd61064a366004614d36565b611030565b34801561065b57600080fd5b506105cd611046565b34801561067057600080fd5b506105cd61106a565b34801561068557600080fd5b5061068e61109b565b6040516105299796959493929190614f4a565b3480156106ad57600080fd5b506105b66106bc366004614d4e565b6110b9565b3480156106cd57600080fd5b5061051c6106dc366004614b3a565b6110e2565b3480156106ed57600080fd5b506106f66110f7565b604051610529919061589e565b34801561070f57600080fd5b506105b661071e366004614d4e565b6110fc565b34801561072f57600080fd5b5061051c61073e366004614c17565b611142565b34801561074f57600080fd5b506105cd61075e366004614c17565b611190565b34801561076f57600080fd5b506105b661077e366004614b3a565b6111f6565b34801561078f57600080fd5b506105b661079e366004614b72565b611241565b3480156107af57600080fd5b506105b66107be366004614c17565b611475565b3480156107cf57600080fd5b506105b66107de366004614d36565b611575565b3480156107ef57600080fd5b506105b66107fe366004614b3a565b611635565b34801561080f57600080fd5b5061051c61081e366004614b3a565b611680565b34801561082f57600080fd5b506105b661083e366004614b3a565b61169e565b34801561084f57600080fd5b5061054761085e366004614b3a565b61171e565b34801561086f57600080fd5b506105b661087e366004614b3a565b611739565b34801561088f57600080fd5b506105b661089e366004614b3a565b611743565b3480156108af57600080fd5b506105cd6108be366004614b3a565b6117ef565b3480156108cf57600080fd5b5061051c61181c565b3480156108e457600080fd5b506105b66108f3366004614bea565b61183d565b34801561090457600080fd5b50610918610913366004614b3a565b61188f565b6040516105299190615877565b34801561093157600080fd5b506105cd610940366004614b3a565b6118a7565b34801561095157600080fd5b506105b66118c2565b34801561096657600080fd5b506105cd610975366004614c17565b61190d565b34801561098657600080fd5b5061098f611b32565b6040516105299493929190614fa9565b3480156109ab57600080fd5b506105b66109ba366004614c17565b611b4a565b3480156109cb57600080fd5b506105cd611c20565b3480156109e057600080fd5b506105cd6109ef366004614b3a565b611c3b565b348015610a0057600080fd5b506105cd611c4d565b348015610a1557600080fd5b506105b6610a24366004614e0b565b611c53565b348015610a3557600080fd5b506105cd6120cc565b348015610a4a57600080fd5b50610547612115565b348015610a5f57600080fd5b5061051c610a6e366004614d4e565b612124565b348015610a7f57600080fd5b5061056961214f565b348015610a9457600080fd5b506105b6612186565b348015610aa957600080fd5b506105cd610ab8366004614d36565b6121cd565b348015610ac957600080fd5b506105cd610ad8366004614b3a565b6121fd565b348015610ae957600080fd5b506105b6610af8366004614e0b565b61220f565b348015610b0957600080fd5b506105cd61226c565b348015610b1e57600080fd5b5061051c610b2d366004614c17565b612271565b348015610b3e57600080fd5b5061051c610b4d366004614c17565b6122d9565b348015610b5e57600080fd5b506105476122ed565b348015610b7357600080fd5b506105b6610b82366004614d36565b6122fc565b348015610b9357600080fd5b506105b6610ba2366004614d36565b6123a1565b348015610bb357600080fd5b506105cd610bc2366004614b3a565b61242e565b348015610bd357600080fd5b506105b6610be2366004614b72565b6124a3565b348015610bf357600080fd5b5061054761269c565b348015610c0857600080fd5b506105b6610c17366004614c42565b6126a2565b348015610c2857600080fd5b5061054761287d565b348015610c3d57600080fd5b506105cd61288c565b348015610c5257600080fd5b506105b6610c61366004614d4e565b6128b0565b348015610c7257600080fd5b506105cd6128cf565b348015610c8757600080fd5b506105cd610c96366004614b72565b6128de565b348015610ca757600080fd5b5061098f612909565b348015610cbc57600080fd5b506105b6610ccb366004614b3a565b612921565b348015610cdc57600080fd5b506105cd612969565b348015610cf157600080fd5b506105cd61298d565b348015610d0657600080fd5b506105b6610d15366004614b3a565b6129b1565b348015610d2657600080fd5b50610d3a610d35366004614ca2565b6129f9565b604051610529929190615888565b348015610d5457600080fd5b506105b6610d63366004614b3a565b612a26565b348015610d7457600080fd5b506105b6610d83366004614b3a565b612a94565b348015610d9457600080fd5b506105b6610da3366004614db2565b612b18565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610dfe5750610dfe82612c7c565b90505b919050565b6039546001600160a01b031681565b60408051808201909152600981527f4368657272795059450000000000000000000000000000000000000000000000602082015290565b6000610e60610e59612cc6565b8484612cca565b5060015b92915050565b610e75600033612124565b610e9a5760405162461bcd60e51b8152600401610e91906151e7565b60405180910390fd5b6032805460ff191695151595909517909455603392909255600060345560355560365543603755603855565b600f5490565b610ef67fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206033612124565b610f125760405162461bcd60e51b8152600401610e91906151e7565b601c54601b546109c491610f32918491610f2c9190612c70565b90612c70565b1115610f505760405162461bcd60e51b8152600401610e91906153a3565b6016819055601a819055602b54610f679082612c70565b602a55602f54610f779082612c70565b602e55610f82612d7e565b50565b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6000610fb6848484612e31565b61102684610fc2612cc6565b61102185604051806060016040528060288152602001615a2c602891396001600160a01b038a166000908152600b6020526040812090611000612cc6565b6001600160a01b031681526020810191909152604001600020549190613037565b612cca565b5060019392505050565b6000908152600160208190526040909120015490565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84881565b600061109661107960006118a7565b61109061108761dead6118a7565b600f5490613063565b90613063565b905090565b60325460335460345460355460365460375460385460ff9096169587565b6110c282611030565b6110d3816110ce612cc6565b61306f565b6110dd83836130d3565b505050565b60156020526000908152604090205460ff1681565b601290565b611104612cc6565b6001600160a01b0316816001600160a01b0316146111345760405162461bcd60e51b8152600401610e919061579c565b61113e828261315b565b5050565b6000610e6061114f612cc6565b8461102185600b6000611160612cc6565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490612c70565b6001600160a01b0382166000908152604160205260408120819081906111b79085906131e0565b91509150816111eb576001600160a01b0385166000908152600c60205260409020546111e690610f2c876118a7565b6111ed565b805b95945050505050565b611201600033612124565b61121d5760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b03166000908152601160205260409020805460ff19166001179055565b61124c600033612124565b6112685760405162461bcd60e51b8152600401610e91906151e7565b603a80546001600160a01b03908116600090815260106020908152604091829020805460ff19169055603980546001600160a01b031990811688861617918290558554168685161790945581517fad5c46480000000000000000000000000000000000000000000000000000000081529151939092169263ad5c464892600480840193919291829003018186803b15801561130257600080fd5b505afa158015611316573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133a9190614b56565b603b80546001600160a01b03199081166001600160a01b03938416178255603a805484166000908152601560209081526040808320805460ff19908116600190811790925585548916855260108452918420805490921617905591549080527f7e7fa33969761a458e04f477e039a608702b4f924981d6653935a8319a08ad7b805491861691841682179055925460139091527f8fa6efc3be94b5b348b21fea823fe8d100408cee9b7f90524494500445d8ff6c80549190941691161790915563d32b9604611407611c20565b6040518263ffffffff1660e01b81526004016114239190614f7c565b602060405180830381600087803b15801561143d57600080fd5b505af1158015611451573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190614cd7565b61149f7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633612124565b6114bb5760405162461bcd60e51b8152600401610e91906151e7565b6a52b7d2dcc80cd2e40000006114d382610f2c610ec6565b11156114f15760405162461bcd60e51b8152600401610e919061536c565b6114fd6000838361328c565b61150782826132e4565b6001600160a01b038281166000908152603c602052604090205416611550576001600160a01b0382166000818152603c6020526040902080546001600160a01b03191690911790555b6001600160a01b038083166000908152603c602052604081205461113e921683613398565b61159f7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84833612124565b6115bb5760405162461bcd60e51b8152600401610e91906150bf565b6115c73360008361328c565b6115d133826134f7565b336000908152603c60205260409020546001600160a01b031661160f57336000818152603c6020526040902080546001600160a01b03191690911790555b336000908152603c6020526040812054610f82916001600160a01b039091169083613398565b611640600033612124565b61165c5760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b03166000908152601060205260409020805460ff19166001179055565b6001600160a01b031660009081526010602052604090205460ff1690565b6116a9600033612124565b6116c55760405162461bcd60e51b8152600401610e91906150bf565b6001600160a01b0381166000908152600d602052604090205460ff166116fd5760405162461bcd60e51b8152600401610e91906152b2565b6001600160a01b03166000908152600d60205260409020805460ff19169055565b603c602052600090815260409020546001600160a01b031681565b610f8233826135c1565b61176d7fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206033612124565b6117895760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b0381166117af5760405162461bcd60e51b8152600401610e9190615055565b601980546001600160a01b039092166001600160a01b03199283168117909155601d8054831682179055602d805483168217905560318054909216179055565b6001600160a01b0381166000908152600a6020908152604080832054600c909252822054610dfe91612c70565b603b5474010000000000000000000000000000000000000000900460ff1681565b611848600033612124565b6118645760405162461bcd60e51b8152600401610e91906150bf565b6001600160a01b03919091166000908152600e60205260409020805460ff1916911515919091179055565b603e6020526000908152604090205463ffffffff1681565b6001600160a01b03166000908152600a602052604090205490565b6118ca612cc6565b6001600160a01b03166118db612115565b6001600160a01b0316146119015760405162461bcd60e51b8152600401610e9190615411565b61190b6000613650565b565b600043821061192e5760405162461bcd60e51b8152600401610e91906156ab565b6001600160a01b0383166000908152603e602052604090205463ffffffff168061195c576000915050610e64565b6001600160a01b0384166000908152603d602052604081208491611981600185615959565b63ffffffff908116825260208201929092526040016000205416116119ea576001600160a01b0384166000908152603d60205260408120906119c4600184615959565b63ffffffff1663ffffffff16815260200190815260200160002060010154915050610e64565b6001600160a01b0384166000908152603d6020908152604080832083805290915290205463ffffffff16831015611a25576000915050610e64565b600080611a33600184615959565b90505b8163ffffffff168163ffffffff161115611afb5760006002611a588484615959565b611a629190615900565b611a6c9083615959565b6001600160a01b0388166000908152603d6020908152604080832063ffffffff8086168552908352928190208151808301909252805490931680825260019093015491810191909152919250871415611acf57602001519450610e649350505050565b805163ffffffff16871115611ae657819350611af4565b611af1600183615959565b92505b5050611a36565b506001600160a01b0385166000908152603d6020908152604080832063ffffffff9094168352929052206001015491505092915050565b601a54601b54601c54601d546001600160a01b031684565b611b747f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84833612124565b611b905760405162461bcd60e51b8152600401610e9190615708565b611b9b8233836136a0565b611ba78260008361328c565b611bb182826134f7565b6001600160a01b038281166000908152603c602052604090205416611bfa576001600160a01b0382166000818152603c6020526040902080546001600160a01b03191690911790555b6001600160a01b038083166000908152603c602052604081205461113e92169083613398565b601854601754601654600092611096929091610f2c91612c70565b603f6020526000908152604090205481565b60095481565b6000805b601454811015611c97576000818152601260205260409020546001600160a01b0316331415611c8557600191505b80611c8f816159c1565b915050611c57565b506039546001600160a01b0316331480611cae5750805b611cca5760405162461bcd60e51b8152600401610e9190615335565b6000611cd5836136e4565b90506014548110156120c6576040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526000906001600160a01b0385169063dd62ed3e90611d2b9033903090600401614ee8565b60206040518083038186803b158015611d4357600080fd5b505afa158015611d57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7b9190614df3565b90508481106120c4576040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038516906323b872dd90611dcd90339030908a90600401614f02565b602060405180830381600087803b158015611de757600080fd5b505af1158015611dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1f9190614cd7565b50603b546001600160a01b0385811691161461200f57603b546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611e66903090600401614ed4565b60206040518083038186803b158015611e7e57600080fd5b505afa158015611e92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb69190614df3565b9050611ec28686613744565b603b546040516370a0823160e01b8152600091611f499184916001600160a01b0316906370a0823190611ef9903090600401614ed4565b60206040518083038186803b158015611f1157600080fd5b505afa158015611f25573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110909190614df3565b90506000611f55611c20565b90506000611f7b82611f75601660000154866138ca90919063ffffffff16565b906138d6565b603b5460195460405163a9059cbb60e01b81529293506001600160a01b039182169263a9059cbb92611fb39216908590600401614f26565b602060405180830381600087803b158015611fcd57600080fd5b505af1158015611fe1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120059190614cd7565b50505050506120c4565b6000612019611c20565b9050600061203982611f756016600001548a6138ca90919063ffffffff16565b60195460405163a9059cbb60e01b81529192506001600160a01b038089169263a9059cbb9261206e9216908590600401614f26565b602060405180830381600087803b15801561208857600080fd5b505af115801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c09190614cd7565b5050505b505b50505050565b60006120d6612cc6565b6001600160a01b03166120e7612115565b6001600160a01b03161461210d5760405162461bcd60e51b8152600401610e9190615411565b6110966138e2565b6000546001600160a01b031690565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60408051808201909152600981527f4348455252595059450000000000000000000000000000000000000000000000602082015290565b61218e612cc6565b6001600160a01b031661219f612115565b6001600160a01b0316146121c55760405162461bcd60e51b8152600401610e9190615411565b610f826138ee565b60008060006121dd8460426131e0565b91509150816121f3576121ee610ec6565b6121f5565b805b949350505050565b600c6020526000908152604090205481565b61221a600033612124565b6122365760405162461bcd60e51b8152600401610e91906151e7565b6040516001600160a01b0382169083156108fc029084906000818181858888f193505050501580156110dd573d6000803e3d6000fd5b600081565b6000610e6061227e612cc6565b8461102185604051806060016040528060258152602001615a8a60259139600b60006122a8612cc6565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190613037565b6000610e606122e6612cc6565b8484612e31565b603b546001600160a01b031681565b6123267fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206033612124565b6123425760405162461bcd60e51b8152600401610e91906151e7565b601c54601a546109c49161235c918491610f2c9190612c70565b111561237a5760405162461bcd60e51b8152600401610e91906153a3565b6017819055601b819055602a546123919082612c70565b602a55602e54610f779082612c70565b6123cb7fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206033612124565b6123e75760405162461bcd60e51b8152600401610e91906151e7565b601a54601b546109c491612401918491610f2c9190612c70565b111561241f5760405162461bcd60e51b8152600401610e91906153a3565b6028819055601c819055603055565b6001600160a01b0381166000908152603e602052604081205463ffffffff168061245957600061249c565b6001600160a01b0383166000908152603d602052604081209061247d600184615959565b63ffffffff1663ffffffff168152602001908152602001600020600101545b9392505050565b603954604080517fc45a015500000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c45a0155916004808301926020929190829003018186803b15801561250157600080fd5b505afa158015612515573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125399190614b56565b9050336001600160a01b038216148061255c57506039546001600160a01b031633145b8061256657503330145b6125825760405162461bcd60e51b8152600401610e9190615335565b61258b83613942565b6110dd576001600160a01b0383811660008181526010602090815260408083208054600160ff199182168117909255601584528285208054909116821790556014805485526012845282852080546001600160a01b0319908116909717905580548552601390935290832080549094169487169490941790925581546126129084906158ac565b90915550506001600160a01b03831663d32b960461262e611c20565b6040518263ffffffff1660e01b815260040161264a9190614f7c565b602060405180830381600087803b15801561266457600080fd5b505af1158015612678573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c69190614cd7565b61dead81565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8666126cd610e15565b805190602001206126dc61398a565b306040516020016126f09493929190614fa9565b60405160208183030381529060405280519060200120905060007fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8888886040516020016127419493929190614f85565b6040516020818303038152906040528051906020012090506000828260405160200161276e929190614e1d565b6040516020818303038152906040528051906020012090506000600182888888604051600081526020016040526040516127ab9493929190614fcd565b6020604051602081039080840390855afa1580156127cd573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166128005760405162461bcd60e51b8152600401610e91906155f1565b6001600160a01b0381166000908152603f60205260408120805491612824836159c1565b9190505589146128465760405162461bcd60e51b8152600401610e919061555d565b874211156128665760405162461bcd60e51b8152600401610e919061573f565b612870818b6135c1565b505050505b505050505050565b603a546001600160a01b031681565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6128b982611030565b6128c5816110ce612cc6565b6110dd838361315b565b6a52b7d2dcc80cd2e400000090565b6001600160a01b039182166000908152600b6020908152604080832093909416825291909152205490565b6016546017546018546019546001600160a01b031684565b61292c600033612124565b6129485760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b03166000908152601160205260409020805460ff19169055565b7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b7fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206081565b6129bc600033612124565b6129d85760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b03166000908152601060205260409020805460ff19169055565b603d6020908152600092835260408084209091529082529020805460019091015463ffffffff9091169082565b612a2e612cc6565b6001600160a01b0316612a3f612115565b6001600160a01b031614612a655760405162461bcd60e51b8152600401610e9190615411565b6001600160a01b038116612a8b5760405162461bcd60e51b8152600401610e919061521e565b610f8281613650565b612a9f600033612124565b612abb5760405162461bcd60e51b8152600401610e91906150bf565b6001600160a01b0381166000908152600d602052604090205460ff1615612af45760405162461bcd60e51b8152600401610e91906150f6565b6001600160a01b03166000908152600d60205260409020805460ff19166001179055565b612b23600033612124565b612b3f5760405162461bcd60e51b8152600401610e91906151e7565b6040516370a0823160e01b815282906001600160a01b038516906370a0823190612b6d903090600401614ed4565b60206040518083038186803b158015612b8557600080fd5b505afa158015612b99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbd9190614df3565b1015612c42576040516370a0823160e01b81526001600160a01b038416906370a0823190612bef903090600401614ed4565b60206040518083038186803b158015612c0757600080fd5b505afa158015612c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3f9190614df3565b91505b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061264a9084908690600401614f26565b600061249c82846158ac565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f01ffc9a70000000000000000000000000000000000000000000000000000000014919050565b3390565b6001600160a01b038316612cf05760405162461bcd60e51b8152600401610e919061518a565b6001600160a01b038216612d165760405162461bcd60e51b8152600401610e919061564e565b6001600160a01b038084166000818152600b602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612d71908590614f7c565b60405180910390a3505050565b60005b601454811015610f82576000818152601260205260409020546001600160a01b031663d32b9604612db0611c20565b6040518263ffffffff1660e01b8152600401612dcc9190614f7c565b602060405180830381600087803b158015612de657600080fd5b505af1158015612dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1e9190614cd7565b5080612e29816159c1565b915050612d81565b6001600160a01b038316612e575760405162461bcd60e51b8152600401610e919061512d565b6001600160a01b038216612e7d5760405162461bcd60e51b8152600401610e91906154a3565b60008111612e9d5760405162461bcd60e51b8152600401610e9190615446565b6001600160a01b0382166000908152600d602052604090205460ff1615612ec357600080fd5b612ece83838361328c565b612ed78161398e565b15612ee457612ee4613a7c565b6001600160a01b0382166000908152600e602052604090205460ff1615612f36576001600160a01b0383166000908152600c6020526040812054612f289083612c70565b9050612f348482613ab8565b505b6001600160a01b0383166000908152600e602052604090205460ff1615612f88576001600160a01b0382166000908152600c6020526040812054612f7a9083613063565b9050612f868382613ab8565b505b6001600160a01b03821660009081526015602052604081205460ff168015612fbe57506039546001600160a01b03858116911614155b8015612fd05750612fce84611680565b155b15612fdd5750600161302b565b6001600160a01b03841660009081526011602052604090205460ff16156130065750600261302b565b6001600160a01b03831660009081526011602052604090205460ff161561302b575060035b6120c684848484613b6e565b6000818484111561305b5760405162461bcd60e51b8152600401610e919190614feb565b505050900390565b600061249c8284615942565b6130798282612124565b61113e57613091816001600160a01b03166014613eef565b61309c836020613eef565b6040516020016130ad929190614e53565b60408051601f198184030181529082905262461bcd60e51b8252610e9191600401614feb565b6130dd8282612124565b61113e5760008281526001602081815260408084206001600160a01b0386168552909152909120805460ff19169091179055613117612cc6565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6131658282612124565b1561113e5760008281526001602090815260408083206001600160a01b03851684529091529020805460ff1916905561319c612cc6565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600080600084116132035760405162461bcd60e51b8152600401610e91906155ba565b61320b6138e2565b84111561322a5760405162461bcd60e51b8152600401610e919061501e565b600061323684866140e6565b845490915081141561324f576000809250925050613285565b600184600101828154811061327457634e487b7160e01b600052603260045260246000fd5b906000526020600020015492509250505b9250929050565b6132978383836110dd565b6001600160a01b0383166132bb576132ae826141c5565b6132b6614200565b6110dd565b6001600160a01b0382166132d2576132ae836141c5565b6132db836141c5565b6110dd826141c5565b6001600160a01b03821661330a5760405162461bcd60e51b8152600401610e91906153da565b600f546133179082612c70565b600f556001600160a01b0382166000908152600a602052604090205461333d9082612c70565b6001600160a01b0383166000818152600a60205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061338c908590614f7c565b60405180910390a35050565b816001600160a01b0316836001600160a01b0316141580156133ba5750600081115b156110dd576001600160a01b0383161561345d576001600160a01b0383166000908152603e602052604081205463ffffffff1690816133fa57600061343d565b6001600160a01b0385166000908152603d602052604081209061341e600185615959565b63ffffffff1663ffffffff168152602001908152602001600020600101545b9050600061344b8285613063565b90506134598684848461420d565b5050505b6001600160a01b038216156110dd576001600160a01b0382166000908152603e602052604081205463ffffffff1690816134985760006134db565b6001600160a01b0384166000908152603d60205260408120906134bc600185615959565b63ffffffff1663ffffffff168152602001908152602001600020600101545b905060006134e98285612c70565b90506128758584848461420d565b6001600160a01b03821661351d5760405162461bcd60e51b8152600401610e9190615500565b61355a81604051806060016040528060228152602001615aaf602291396001600160a01b0385166000908152600a60205260409020549190613037565b6001600160a01b0383166000908152600a6020526040902055600f546135809082613063565b600f556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061338c908590614f7c565b6001600160a01b038083166000908152603c6020526040812054909116906135e8846118a7565b6001600160a01b038581166000818152603c602052604080822080546001600160a01b031916898616908117909155905194955093928616927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46120c6828483613398565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006136ac84846128de565b905060001981146120c657818110156136d75760405162461bcd60e51b8152600401610e919061527b565b6120c68484848403612cca565b60008060145460016136f691906158ac565b905060005b60145481101561373d576000818152601360205260409020546001600160a01b038581169116141561372b578091505b80613735816159c1565b9150506136fb565b5092915050565b604080516002808252606082018352600092602083019080368337019050509050818160008151811061378757634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152603b548251911690829060019081106137c657634e487b7160e01b600052603260045260246000fd5b6001600160a01b03928316602091820292909201015260395460405163095ea7b360e01b81528483169263095ea7b392613807929116908790600401614f26565b602060405180830381600087803b15801561382157600080fd5b505af1158015613835573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138599190614cd7565b50603954604051635c11d79560e01b81526001600160a01b0390911690635c11d795906138939086906000908690309042906004016157f9565b600060405180830381600087803b1580156138ad57600080fd5b505af11580156138c1573d6000803e3d6000fd5b50505050505050565b600061249c8284615923565b600061249c82846158ec565b600061109660406143ae565b60006138fa60406143b2565b60006139046138e2565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67816040516139359190614f7c565b60405180910390a1905090565b600080805b60145481101561373d576000818152601260205260409020546001600160a01b038581169116141561397857600191505b80613982816159c1565b915050613947565b4690565b603a546000906001600160a01b031633148015906139b65750603b54600160a81b900460ff16155b80156139c4575060325460ff165b80156139df575060365460375443916139dc916158ac565b11155b8015613a6c5750603554603b546040516370a0823160e01b81526001600160a01b03909116906370a0823190613a19903090600401614ed4565b60206040518083038186803b158015613a3157600080fd5b505afa158015613a45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a699190614df3565b10155b8015610dfe575050603854111590565b603554613a8b9061dead6143bb565b43603755603554603454613a9e91612c70565b6034819055603354101561190b576032805460ff19169055565b600081118015613ade57506001600160a01b0382166000908152600c6020526040902054155b15613af157613aec82614574565b613b24565b80158015613b1657506001600160a01b0382166000908152600c602052604090205415155b15613b2457613b24826145d5565b6001600160a01b0382166000908152600c6020526040902054600954613b4f918391610f2c91613063565b6009556001600160a01b039091166000908152600c6020526040902055565b60ff8116613b8357613b7e614722565b613bbf565b8060ff1660011415613b9757613b7e61477c565b8060ff1660021415613bab57613b7e6147d6565b8060ff1660031415613bbf57613bbf614830565b6000613bca8361488a565b9050613c3b836040518060400160405280601481526020017f496e73756666696369656e742042616c616e6365000000000000000000000000815250600a6000896001600160a01b03166001600160a01b03168152602001908152602001600020546130379092919063ffffffff16565b6001600160a01b038087166000908152600a602052604080822093909355835191871681529190912054613c6e91612c70565b6001600160a01b0385166000908152600a6020526040902055613c9081614911565b836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360000151604051613cd79190614f7c565b60405180910390a36001600160a01b038581166000908152603c602052604090205416613d28576001600160a01b0385166000818152603c6020526040902080546001600160a01b03191690911790555b6001600160a01b038481166000908152603c602052604090205416613d71576001600160a01b0384166000818152603c6020526040902080546001600160a01b03191690911790555b8051831415613db1576001600160a01b038086166000908152603c6020526040808220548784168352912054613dac92918216911685613398565b613e53565b6001600160a01b038086166000908152603c60205260408082205487841683529120548351613de893928316929190911690613398565b6001600160a01b038086166000908152603c60209081526040808320546019548516845292205490840151613e2593928316929190911690613398565b6001600160a01b038086166000908152603c60205260408120546060840151613e5393919091169190613398565b60ff82161580613e6657508160ff166001145b15613e7857613e73614939565b6120c4565b8160ff1660021480613e8d57508160ff166003145b156120c457613e9a614939565b60195460208201516040516001600160a01b03928316928816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91613ee09190614f7c565b60405180910390a35050505050565b60606000613efe836002615923565b613f099060026158ac565b67ffffffffffffffff811115613f2f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613f59576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613f9e57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613ff757634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600061401b846002615923565b6140269060016158ac565b90505b60018111156140c7577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061407557634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061409957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c936140c0816159aa565b9050614029565b50831561249c5760405162461bcd60e51b8152600401610e919061508a565b81546000906140f757506000610e64565b82546000905b80821015614161576000614111838361496f565b90508486828154811061413457634e487b7160e01b600052603260045260246000fd5b9060005260206000200154111561414d5780915061415b565b6141588160016158ac565b92505b506140fd565b6000821180156141a457508385614179600185615942565b8154811061419757634e487b7160e01b600052603260045260246000fd5b9060005260206000200154145b156141bd576141b4600183615942565b92505050610e64565b509050610e64565b6001600160a01b0381166000908152604160209081526040808320600c90925290912054610f8291906141fb90610f2c856118a7565b61498a565b61190b60426141fb610ec6565b600061423143604051806060016040528060368152602001615a54603691396149d4565b905060008463ffffffff1611801561428b57506001600160a01b0385166000908152603d6020526040812063ffffffff83169161426f600188615959565b63ffffffff908116825260208201929092526040016000205416145b156142d4576001600160a01b0385166000908152603d6020526040812083916142b5600188615959565b63ffffffff168152602081019190915260400160002060010155614364565b60408051808201825263ffffffff838116825260208083018681526001600160a01b038a166000908152603d83528581208a851682529092529390209151825463ffffffff1916911617815590516001918201556143339085906158c4565b6001600160a01b0386166000908152603e60205260409020805463ffffffff191663ffffffff929092169190911790555b846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724848460405161439f929190615869565b60405180910390a25050505050565b5490565b80546001019055565b603b805460ff60a81b1916600160a81b1790556040805160028082526060820183526000926020830190803683375050603b5482519293506001600160a01b03169183915060009061441d57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050308160018151811061445f57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152603b5460395460405163095ea7b360e01b81529183169263095ea7b3926144a492909116908790600401614f26565b602060405180830381600087803b1580156144be57600080fd5b505af11580156144d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144f69190614cd7565b50603954604051635c11d79560e01b81526001600160a01b0390911690635c11d795906145309086906000908690889042906004016157f9565b600060405180830381600087803b15801561454a57600080fd5b505af115801561455e573d6000803e3d6000fd5b5050603b805460ff60a81b191690555050505050565b600780546001600160a01b039092166000818152600860205260408120849055600184018355919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68890910180546001600160a01b0319169091179055565b600780546145e590600190615942565b8154811061460357634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b038481168452600890925260409092205460078054929093169291811061464f57634e487b7160e01b600052603260045260246000fd5b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905591831681526008918290526040812054600780549193929161469b90600190615942565b815481106146b957634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b0316835282019290925260400190205560078054806146fd57634e487b7160e01b600052603160045260246000fd5b600082815260209020810160001990810180546001600160a01b031916905501905550565b60168054601e5560178054601f556018805460205560198054602180546001600160a01b038084166001600160a01b0319928316179092556022549096556023549094556024549092556025549092169216919091179055565b60168054601e5560178054601f556018805460205560198054602180546001600160a01b038084166001600160a01b0319928316179092556026549096556027549094556028549092556029549092169216919091179055565b60168054601e5560178054601f556018805460205560198054602180546001600160a01b038084166001600160a01b031992831617909255602a54909655602b54909455602c54909255602d549092169216919091179055565b60168054601e5560178054601f556018805460205560198054602180546001600160a01b038084166001600160a01b031992831617909255602e54909655602f549094556030549092556031549092169216919091179055565b614892614b12565b60006040518060800160405280600081526020016148b585601660000154614a04565b81526020016148c985601660010154614a04565b81526020016148dd85601660020154614a04565b81525090506149098160600151611090836040015161109085602001518861306390919063ffffffff16565b815292915050565b602081015160195461492c91906001600160a01b0316614a23565b610f828160600151614a80565b601e54601655601f54601755602054601855602154601980546001600160a01b0319166001600160a01b03909216919091179055565b600061497e60028484186158ec565b61249c908484166158ac565b60006149946138e2565b9050806149a084614ac1565b10156110dd578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b60008164010000000084106149fc5760405162461bcd60e51b8152600401610e919190614feb565b509192915050565b600081614a1357506000610e64565b61249c612710611f7585856138ca565b6001600160a01b038116614a365761113e565b81614a405761113e565b6001600160a01b0381166000908152600a6020526040902054614a639083612c70565b6001600160a01b0382166000908152600a60205260409020555050565b80614a8a57610f82565b306000908152600a6020526040902054614aa49082612c70565b306000818152600a6020526040902091909155610f8290826134f7565b8054600090614ad257506000610e01565b81548290614ae290600190615942565b81548110614b0057634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050610e01565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b600060208284031215614b4b578081fd5b813561249c81615a08565b600060208284031215614b67578081fd5b815161249c81615a08565b60008060408385031215614b84578081fd5b8235614b8f81615a08565b91506020830135614b9f81615a08565b809150509250929050565b600080600060608486031215614bbe578081fd5b8335614bc981615a08565b92506020840135614bd981615a08565b929592945050506040919091013590565b60008060408385031215614bfc578182fd5b8235614c0781615a08565b91506020830135614b9f81615a1d565b60008060408385031215614c29578182fd5b8235614c3481615a08565b946020939093013593505050565b60008060008060008060c08789031215614c5a578182fd5b8635614c6581615a08565b95506020870135945060408701359350606087013560ff81168114614c88578283fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215614cb4578182fd5b8235614cbf81615a08565b9150602083013563ffffffff81168114614b9f578182fd5b600060208284031215614ce8578081fd5b815161249c81615a1d565b600080600080600060a08688031215614d0a578081fd5b8535614d1581615a1d565b97602087013597506040870135966060810135965060800135945092505050565b600060208284031215614d47578081fd5b5035919050565b60008060408385031215614d60578081fd5b823591506020830135614b9f81615a08565b600060208284031215614d83578081fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461249c578182fd5b600080600060608486031215614dc6578081fd5b8335614dd181615a08565b9250602084013591506040840135614de881615a08565b809150509250925092565b600060208284031215614e04578081fd5b5051919050565b60008060408385031215614d60578182fd5b7f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b60007f416363657373436f6e74726f6c3a206163636f756e742000000000000000000082528351614e8b81601785016020880161597e565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614ec881602884016020880161597e565b01602801949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b9615158752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b90815260200190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b93845260ff9290921660208401526040830152606082015260800190565b600060208252825180602084015261500a81604085016020870161597e565b601f01601f19169190910160400192915050565b6020808252601d908201527f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000604082015260600190565b6020808252818101527f5059453a2041646472657373205a65726f206973206e6f7420616c6c6f776564604082015260600190565b6020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b60208082526011908201527f4655454c3a204e4f545f414c4c4f574544000000000000000000000000000000604082015260600190565b6020808252601f908201527f4164647265737320697320616c726561647920626c61636b6c69737465642100604082015260600190565b60208082526025908201527f42455032303a207472616e736665722066726f6d20746865207a65726f20616460408201527f6472657373000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f42455032303a20617070726f76652066726f6d20746865207a65726f2061646460408201527f7265737300000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526013908201527f4348455252593a204e4f545f414c4c4f57454400000000000000000000000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201527f6464726573730000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604082015260600190565b6020808252604c908201527f4164647265737320686173206e6f74206265656e20626c61636b6c697374656460408201527f2120456e74657220616e20616464726573732074686174206973206f6e20746860608201527f6520626c61636b6c6973742e0000000000000000000000000000000000000000608082015260a00190565b60208082526010908201527f5059453a204e4f545f414c4c4f57454400000000000000000000000000000000604082015260600190565b6020808252601a908201527f4348455252593a20524541434845445f4d41585f535550504c59000000000000604082015260600190565b60208082526016908201527f4665657320657863656564206d6178206c696d69742e00000000000000000000604082015260600190565b6020808252601f908201527f42455032303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f5472616e7366657220616d6f756e74206d75737420626520677265617465722060408201527f7468616e207a65726f0000000000000000000000000000000000000000000000606082015260800190565b60208082526023908201527f42455032303a207472616e7366657220746f20746865207a65726f206164647260408201527f6573730000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f42455032303a206275726e2066726f6d20746865207a65726f2061646472657360408201527f7300000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4348455252593a3a64656c656761746542795369673a20696e76616c6964206e60408201527f6f6e636500000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526016908201527f4552433230536e617073686f743a206964206973203000000000000000000000604082015260600190565b60208082526028908201527f4348455252593a3a64656c656761746542795369673a20696e76616c6964207360408201527f69676e6174757265000000000000000000000000000000000000000000000000606082015260800190565b60208082526022908201527f42455032303a20617070726f766520746f20746865207a65726f20616464726560408201527f7373000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f4348455252593a3a6765745072696f72566f7465733a206e6f7420796574206460408201527f657465726d696e65640000000000000000000000000000000000000000000000606082015260800190565b60208082526012908201527f4150504c453a204e4f545f414c4c4f5745440000000000000000000000000000604082015260600190565b60208082526028908201527f4348455252593a3a64656c656761746542795369673a207369676e617475726560408201527f2065787069726564000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560408201527f20726f6c657320666f722073656c660000000000000000000000000000000000606082015260800190565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b818110156158485784516001600160a01b031683529383019391830191600101615823565b50506001600160a01b03969096166060850152505050608001529392505050565b918252602082015260400190565b63ffffffff91909116815260200190565b63ffffffff929092168252602082015260400190565b60ff91909116815260200190565b600082198211156158bf576158bf6159dc565b500190565b600063ffffffff8083168185168083038211156158e3576158e36159dc565b01949350505050565b6000826158fb576158fb6159f2565b500490565b600063ffffffff80841680615917576159176159f2565b92169190910492915050565b600081600019048311821515161561593d5761593d6159dc565b500290565b600082821015615954576159546159dc565b500390565b600063ffffffff83811690831681811015615976576159766159dc565b039392505050565b60005b83811015615999578181015183820152602001615981565b838111156120c65750506000910152565b6000816159b9576159b96159dc565b506000190190565b60006000198214156159d5576159d56159dc565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b0381168114610f8257600080fd5b8015158114610f8257600080fdfe42455032303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654348455252593a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d6265722065786365656473203332206269747342455032303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f42455032303a206275726e20616d6f756e7420657863656564732062616c616e6365a26469706673582212207d80752e756f0d892146cef769378108ea493345c6c5342c3d7921f068e687f664736f6c634300080100330000000000000000000000004f71e29c3d5934a15308005b19ca263061e99616000000000000000000000000c71b2b3dd4a0a72f8857e4f5fbac53b401f2735500000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000003e8

Deployed Bytecode

0x6080604052600436106104f05760003560e01c806379cc679011610294578063b4b5ea571161015e578063dfd66cb3116100d6578063f1127ed81161008a578063f3290d751161006f578063f3290d7514610d68578063f8a67a6214610d88578063f8b2cb4f14610925576104f7565b8063f1127ed814610d1a578063f2fde38b14610d48576104f7565b8063e7a324dc116100bb578063e7a324dc14610cd0578063e934768314610ce5578063ea2f0b3714610cfa576104f7565b8063dfd66cb314610c9b578063e284db3e14610cb0576104f7565b8063c80bbbeb1161012d578063d547741f11610112578063d547741f14610c46578063d5abeb0114610c66578063dd62ed3e14610c7b576104f7565b8063c80bbbeb14610c1c578063d539139314610c31576104f7565b8063b4b5ea5714610ba7578063b6f3e08714610bc7578063bd3900c014610be7578063c3cda52014610bfc576104f7565b80639711715a1161020c578063a457c2d7116101c0578063ad5c4648116101a5578063ad5c464814610b52578063af2f6dd814610b67578063b0a863f914610b87576104f7565b8063a457c2d714610b12578063a9059cbb14610b32576104f7565b806398807d84116101f157806398807d8414610abd578063a0558c3f14610add578063a217fddf14610afd576104f7565b80639711715a14610a88578063981b24d014610a9d576104f7565b80638283bbf3116102635780638da5cb5b116102485780638da5cb5b14610a3e57806391d1485414610a5357806395d89b4114610a73576104f7565b80638283bbf314610a0957806382ccff8914610a29576104f7565b806379cc67901461099f5780637ae316d0146109bf5780637ecebe00146109d4578063817b1cd2146109f4576104f7565b80633bf33976116103d55780635c19a95c1161034d5780636fcfff4511610301578063715018a6116102e6578063715018a614610945578063782d6fe11461095a5780637891b5101461097a576104f7565b80636fcfff45146108f857806370a0823114610925576104f7565b80636baa9a57116103325780636baa9a57146108a35780636ddd1713146108c35780636ed52e68146108d8576104f7565b80635c19a95c1461086357806367243ea814610883576104f7565b806342966c68116103a45780635342acb4116103895780635342acb414610803578063537df3b614610823578063587cde1e14610843576104f7565b806342966c68146107c3578063437823ec146107e3576104f7565b80633bf33976146107435780633d8a62d31461076357806340b28c2f1461078357806340c10f19146107a3576104f7565b8063248a9ca3116104685780632f2ff15d11610437578063313ce5671161041c578063313ce567146106e157806336568abe146107035780633950935114610723576104f7565b80632f2ff15d146106a157806330367554146106c1576104f7565b8063248a9ca31461062f578063282c51f31461064f5780632b112e49146106645780632c77735c14610679576104f7565b8063174ca3ec116104bf5780631973dc37116104a45780631973dc37146105da57806320606b70146105fa57806323b872dd1461060f576104f7565b8063174ca3ec1461059657806318160ddd146105b8576104f7565b806301ffc9a7146104fc57806302e8e85f1461053257806306fdde0314610554578063095ea7b314610576576104f7565b366104f757005b600080fd5b34801561050857600080fd5b5061051c610517366004614d72565b610da8565b6040516105299190614f3f565b60405180910390f35b34801561053e57600080fd5b50610547610e06565b6040516105299190614ed4565b34801561056057600080fd5b50610569610e15565b6040516105299190614feb565b34801561058257600080fd5b5061051c610591366004614c17565b610e4c565b3480156105a257600080fd5b506105b66105b1366004614cf3565b610e6a565b005b3480156105c457600080fd5b506105cd610ec6565b6040516105299190614f7c565b3480156105e657600080fd5b506105b66105f5366004614d36565b610ecc565b34801561060657600080fd5b506105cd610f85565b34801561061b57600080fd5b5061051c61062a366004614baa565b610fa9565b34801561063b57600080fd5b506105cd61064a366004614d36565b611030565b34801561065b57600080fd5b506105cd611046565b34801561067057600080fd5b506105cd61106a565b34801561068557600080fd5b5061068e61109b565b6040516105299796959493929190614f4a565b3480156106ad57600080fd5b506105b66106bc366004614d4e565b6110b9565b3480156106cd57600080fd5b5061051c6106dc366004614b3a565b6110e2565b3480156106ed57600080fd5b506106f66110f7565b604051610529919061589e565b34801561070f57600080fd5b506105b661071e366004614d4e565b6110fc565b34801561072f57600080fd5b5061051c61073e366004614c17565b611142565b34801561074f57600080fd5b506105cd61075e366004614c17565b611190565b34801561076f57600080fd5b506105b661077e366004614b3a565b6111f6565b34801561078f57600080fd5b506105b661079e366004614b72565b611241565b3480156107af57600080fd5b506105b66107be366004614c17565b611475565b3480156107cf57600080fd5b506105b66107de366004614d36565b611575565b3480156107ef57600080fd5b506105b66107fe366004614b3a565b611635565b34801561080f57600080fd5b5061051c61081e366004614b3a565b611680565b34801561082f57600080fd5b506105b661083e366004614b3a565b61169e565b34801561084f57600080fd5b5061054761085e366004614b3a565b61171e565b34801561086f57600080fd5b506105b661087e366004614b3a565b611739565b34801561088f57600080fd5b506105b661089e366004614b3a565b611743565b3480156108af57600080fd5b506105cd6108be366004614b3a565b6117ef565b3480156108cf57600080fd5b5061051c61181c565b3480156108e457600080fd5b506105b66108f3366004614bea565b61183d565b34801561090457600080fd5b50610918610913366004614b3a565b61188f565b6040516105299190615877565b34801561093157600080fd5b506105cd610940366004614b3a565b6118a7565b34801561095157600080fd5b506105b66118c2565b34801561096657600080fd5b506105cd610975366004614c17565b61190d565b34801561098657600080fd5b5061098f611b32565b6040516105299493929190614fa9565b3480156109ab57600080fd5b506105b66109ba366004614c17565b611b4a565b3480156109cb57600080fd5b506105cd611c20565b3480156109e057600080fd5b506105cd6109ef366004614b3a565b611c3b565b348015610a0057600080fd5b506105cd611c4d565b348015610a1557600080fd5b506105b6610a24366004614e0b565b611c53565b348015610a3557600080fd5b506105cd6120cc565b348015610a4a57600080fd5b50610547612115565b348015610a5f57600080fd5b5061051c610a6e366004614d4e565b612124565b348015610a7f57600080fd5b5061056961214f565b348015610a9457600080fd5b506105b6612186565b348015610aa957600080fd5b506105cd610ab8366004614d36565b6121cd565b348015610ac957600080fd5b506105cd610ad8366004614b3a565b6121fd565b348015610ae957600080fd5b506105b6610af8366004614e0b565b61220f565b348015610b0957600080fd5b506105cd61226c565b348015610b1e57600080fd5b5061051c610b2d366004614c17565b612271565b348015610b3e57600080fd5b5061051c610b4d366004614c17565b6122d9565b348015610b5e57600080fd5b506105476122ed565b348015610b7357600080fd5b506105b6610b82366004614d36565b6122fc565b348015610b9357600080fd5b506105b6610ba2366004614d36565b6123a1565b348015610bb357600080fd5b506105cd610bc2366004614b3a565b61242e565b348015610bd357600080fd5b506105b6610be2366004614b72565b6124a3565b348015610bf357600080fd5b5061054761269c565b348015610c0857600080fd5b506105b6610c17366004614c42565b6126a2565b348015610c2857600080fd5b5061054761287d565b348015610c3d57600080fd5b506105cd61288c565b348015610c5257600080fd5b506105b6610c61366004614d4e565b6128b0565b348015610c7257600080fd5b506105cd6128cf565b348015610c8757600080fd5b506105cd610c96366004614b72565b6128de565b348015610ca757600080fd5b5061098f612909565b348015610cbc57600080fd5b506105b6610ccb366004614b3a565b612921565b348015610cdc57600080fd5b506105cd612969565b348015610cf157600080fd5b506105cd61298d565b348015610d0657600080fd5b506105b6610d15366004614b3a565b6129b1565b348015610d2657600080fd5b50610d3a610d35366004614ca2565b6129f9565b604051610529929190615888565b348015610d5457600080fd5b506105b6610d63366004614b3a565b612a26565b348015610d7457600080fd5b506105b6610d83366004614b3a565b612a94565b348015610d9457600080fd5b506105b6610da3366004614db2565b612b18565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610dfe5750610dfe82612c7c565b90505b919050565b6039546001600160a01b031681565b60408051808201909152600981527f4368657272795059450000000000000000000000000000000000000000000000602082015290565b6000610e60610e59612cc6565b8484612cca565b5060015b92915050565b610e75600033612124565b610e9a5760405162461bcd60e51b8152600401610e91906151e7565b60405180910390fd5b6032805460ff191695151595909517909455603392909255600060345560355560365543603755603855565b600f5490565b610ef67fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206033612124565b610f125760405162461bcd60e51b8152600401610e91906151e7565b601c54601b546109c491610f32918491610f2c9190612c70565b90612c70565b1115610f505760405162461bcd60e51b8152600401610e91906153a3565b6016819055601a819055602b54610f679082612c70565b602a55602f54610f779082612c70565b602e55610f82612d7e565b50565b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6000610fb6848484612e31565b61102684610fc2612cc6565b61102185604051806060016040528060288152602001615a2c602891396001600160a01b038a166000908152600b6020526040812090611000612cc6565b6001600160a01b031681526020810191909152604001600020549190613037565b612cca565b5060019392505050565b6000908152600160208190526040909120015490565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84881565b600061109661107960006118a7565b61109061108761dead6118a7565b600f5490613063565b90613063565b905090565b60325460335460345460355460365460375460385460ff9096169587565b6110c282611030565b6110d3816110ce612cc6565b61306f565b6110dd83836130d3565b505050565b60156020526000908152604090205460ff1681565b601290565b611104612cc6565b6001600160a01b0316816001600160a01b0316146111345760405162461bcd60e51b8152600401610e919061579c565b61113e828261315b565b5050565b6000610e6061114f612cc6565b8461102185600b6000611160612cc6565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490612c70565b6001600160a01b0382166000908152604160205260408120819081906111b79085906131e0565b91509150816111eb576001600160a01b0385166000908152600c60205260409020546111e690610f2c876118a7565b6111ed565b805b95945050505050565b611201600033612124565b61121d5760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b03166000908152601160205260409020805460ff19166001179055565b61124c600033612124565b6112685760405162461bcd60e51b8152600401610e91906151e7565b603a80546001600160a01b03908116600090815260106020908152604091829020805460ff19169055603980546001600160a01b031990811688861617918290558554168685161790945581517fad5c46480000000000000000000000000000000000000000000000000000000081529151939092169263ad5c464892600480840193919291829003018186803b15801561130257600080fd5b505afa158015611316573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133a9190614b56565b603b80546001600160a01b03199081166001600160a01b03938416178255603a805484166000908152601560209081526040808320805460ff19908116600190811790925585548916855260108452918420805490921617905591549080527f7e7fa33969761a458e04f477e039a608702b4f924981d6653935a8319a08ad7b805491861691841682179055925460139091527f8fa6efc3be94b5b348b21fea823fe8d100408cee9b7f90524494500445d8ff6c80549190941691161790915563d32b9604611407611c20565b6040518263ffffffff1660e01b81526004016114239190614f7c565b602060405180830381600087803b15801561143d57600080fd5b505af1158015611451573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190614cd7565b61149f7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633612124565b6114bb5760405162461bcd60e51b8152600401610e91906151e7565b6a52b7d2dcc80cd2e40000006114d382610f2c610ec6565b11156114f15760405162461bcd60e51b8152600401610e919061536c565b6114fd6000838361328c565b61150782826132e4565b6001600160a01b038281166000908152603c602052604090205416611550576001600160a01b0382166000818152603c6020526040902080546001600160a01b03191690911790555b6001600160a01b038083166000908152603c602052604081205461113e921683613398565b61159f7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84833612124565b6115bb5760405162461bcd60e51b8152600401610e91906150bf565b6115c73360008361328c565b6115d133826134f7565b336000908152603c60205260409020546001600160a01b031661160f57336000818152603c6020526040902080546001600160a01b03191690911790555b336000908152603c6020526040812054610f82916001600160a01b039091169083613398565b611640600033612124565b61165c5760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b03166000908152601060205260409020805460ff19166001179055565b6001600160a01b031660009081526010602052604090205460ff1690565b6116a9600033612124565b6116c55760405162461bcd60e51b8152600401610e91906150bf565b6001600160a01b0381166000908152600d602052604090205460ff166116fd5760405162461bcd60e51b8152600401610e91906152b2565b6001600160a01b03166000908152600d60205260409020805460ff19169055565b603c602052600090815260409020546001600160a01b031681565b610f8233826135c1565b61176d7fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206033612124565b6117895760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b0381166117af5760405162461bcd60e51b8152600401610e9190615055565b601980546001600160a01b039092166001600160a01b03199283168117909155601d8054831682179055602d805483168217905560318054909216179055565b6001600160a01b0381166000908152600a6020908152604080832054600c909252822054610dfe91612c70565b603b5474010000000000000000000000000000000000000000900460ff1681565b611848600033612124565b6118645760405162461bcd60e51b8152600401610e91906150bf565b6001600160a01b03919091166000908152600e60205260409020805460ff1916911515919091179055565b603e6020526000908152604090205463ffffffff1681565b6001600160a01b03166000908152600a602052604090205490565b6118ca612cc6565b6001600160a01b03166118db612115565b6001600160a01b0316146119015760405162461bcd60e51b8152600401610e9190615411565b61190b6000613650565b565b600043821061192e5760405162461bcd60e51b8152600401610e91906156ab565b6001600160a01b0383166000908152603e602052604090205463ffffffff168061195c576000915050610e64565b6001600160a01b0384166000908152603d602052604081208491611981600185615959565b63ffffffff908116825260208201929092526040016000205416116119ea576001600160a01b0384166000908152603d60205260408120906119c4600184615959565b63ffffffff1663ffffffff16815260200190815260200160002060010154915050610e64565b6001600160a01b0384166000908152603d6020908152604080832083805290915290205463ffffffff16831015611a25576000915050610e64565b600080611a33600184615959565b90505b8163ffffffff168163ffffffff161115611afb5760006002611a588484615959565b611a629190615900565b611a6c9083615959565b6001600160a01b0388166000908152603d6020908152604080832063ffffffff8086168552908352928190208151808301909252805490931680825260019093015491810191909152919250871415611acf57602001519450610e649350505050565b805163ffffffff16871115611ae657819350611af4565b611af1600183615959565b92505b5050611a36565b506001600160a01b0385166000908152603d6020908152604080832063ffffffff9094168352929052206001015491505092915050565b601a54601b54601c54601d546001600160a01b031684565b611b747f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84833612124565b611b905760405162461bcd60e51b8152600401610e9190615708565b611b9b8233836136a0565b611ba78260008361328c565b611bb182826134f7565b6001600160a01b038281166000908152603c602052604090205416611bfa576001600160a01b0382166000818152603c6020526040902080546001600160a01b03191690911790555b6001600160a01b038083166000908152603c602052604081205461113e92169083613398565b601854601754601654600092611096929091610f2c91612c70565b603f6020526000908152604090205481565b60095481565b6000805b601454811015611c97576000818152601260205260409020546001600160a01b0316331415611c8557600191505b80611c8f816159c1565b915050611c57565b506039546001600160a01b0316331480611cae5750805b611cca5760405162461bcd60e51b8152600401610e9190615335565b6000611cd5836136e4565b90506014548110156120c6576040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526000906001600160a01b0385169063dd62ed3e90611d2b9033903090600401614ee8565b60206040518083038186803b158015611d4357600080fd5b505afa158015611d57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7b9190614df3565b90508481106120c4576040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038516906323b872dd90611dcd90339030908a90600401614f02565b602060405180830381600087803b158015611de757600080fd5b505af1158015611dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1f9190614cd7565b50603b546001600160a01b0385811691161461200f57603b546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611e66903090600401614ed4565b60206040518083038186803b158015611e7e57600080fd5b505afa158015611e92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb69190614df3565b9050611ec28686613744565b603b546040516370a0823160e01b8152600091611f499184916001600160a01b0316906370a0823190611ef9903090600401614ed4565b60206040518083038186803b158015611f1157600080fd5b505afa158015611f25573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110909190614df3565b90506000611f55611c20565b90506000611f7b82611f75601660000154866138ca90919063ffffffff16565b906138d6565b603b5460195460405163a9059cbb60e01b81529293506001600160a01b039182169263a9059cbb92611fb39216908590600401614f26565b602060405180830381600087803b158015611fcd57600080fd5b505af1158015611fe1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120059190614cd7565b50505050506120c4565b6000612019611c20565b9050600061203982611f756016600001548a6138ca90919063ffffffff16565b60195460405163a9059cbb60e01b81529192506001600160a01b038089169263a9059cbb9261206e9216908590600401614f26565b602060405180830381600087803b15801561208857600080fd5b505af115801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c09190614cd7565b5050505b505b50505050565b60006120d6612cc6565b6001600160a01b03166120e7612115565b6001600160a01b03161461210d5760405162461bcd60e51b8152600401610e9190615411565b6110966138e2565b6000546001600160a01b031690565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60408051808201909152600981527f4348455252595059450000000000000000000000000000000000000000000000602082015290565b61218e612cc6565b6001600160a01b031661219f612115565b6001600160a01b0316146121c55760405162461bcd60e51b8152600401610e9190615411565b610f826138ee565b60008060006121dd8460426131e0565b91509150816121f3576121ee610ec6565b6121f5565b805b949350505050565b600c6020526000908152604090205481565b61221a600033612124565b6122365760405162461bcd60e51b8152600401610e91906151e7565b6040516001600160a01b0382169083156108fc029084906000818181858888f193505050501580156110dd573d6000803e3d6000fd5b600081565b6000610e6061227e612cc6565b8461102185604051806060016040528060258152602001615a8a60259139600b60006122a8612cc6565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190613037565b6000610e606122e6612cc6565b8484612e31565b603b546001600160a01b031681565b6123267fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206033612124565b6123425760405162461bcd60e51b8152600401610e91906151e7565b601c54601a546109c49161235c918491610f2c9190612c70565b111561237a5760405162461bcd60e51b8152600401610e91906153a3565b6017819055601b819055602a546123919082612c70565b602a55602e54610f779082612c70565b6123cb7fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206033612124565b6123e75760405162461bcd60e51b8152600401610e91906151e7565b601a54601b546109c491612401918491610f2c9190612c70565b111561241f5760405162461bcd60e51b8152600401610e91906153a3565b6028819055601c819055603055565b6001600160a01b0381166000908152603e602052604081205463ffffffff168061245957600061249c565b6001600160a01b0383166000908152603d602052604081209061247d600184615959565b63ffffffff1663ffffffff168152602001908152602001600020600101545b9392505050565b603954604080517fc45a015500000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c45a0155916004808301926020929190829003018186803b15801561250157600080fd5b505afa158015612515573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125399190614b56565b9050336001600160a01b038216148061255c57506039546001600160a01b031633145b8061256657503330145b6125825760405162461bcd60e51b8152600401610e9190615335565b61258b83613942565b6110dd576001600160a01b0383811660008181526010602090815260408083208054600160ff199182168117909255601584528285208054909116821790556014805485526012845282852080546001600160a01b0319908116909717905580548552601390935290832080549094169487169490941790925581546126129084906158ac565b90915550506001600160a01b03831663d32b960461262e611c20565b6040518263ffffffff1660e01b815260040161264a9190614f7c565b602060405180830381600087803b15801561266457600080fd5b505af1158015612678573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c69190614cd7565b61dead81565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8666126cd610e15565b805190602001206126dc61398a565b306040516020016126f09493929190614fa9565b60405160208183030381529060405280519060200120905060007fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8888886040516020016127419493929190614f85565b6040516020818303038152906040528051906020012090506000828260405160200161276e929190614e1d565b6040516020818303038152906040528051906020012090506000600182888888604051600081526020016040526040516127ab9493929190614fcd565b6020604051602081039080840390855afa1580156127cd573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166128005760405162461bcd60e51b8152600401610e91906155f1565b6001600160a01b0381166000908152603f60205260408120805491612824836159c1565b9190505589146128465760405162461bcd60e51b8152600401610e919061555d565b874211156128665760405162461bcd60e51b8152600401610e919061573f565b612870818b6135c1565b505050505b505050505050565b603a546001600160a01b031681565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6128b982611030565b6128c5816110ce612cc6565b6110dd838361315b565b6a52b7d2dcc80cd2e400000090565b6001600160a01b039182166000908152600b6020908152604080832093909416825291909152205490565b6016546017546018546019546001600160a01b031684565b61292c600033612124565b6129485760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b03166000908152601160205260409020805460ff19169055565b7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b7fe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f8818206081565b6129bc600033612124565b6129d85760405162461bcd60e51b8152600401610e91906151e7565b6001600160a01b03166000908152601060205260409020805460ff19169055565b603d6020908152600092835260408084209091529082529020805460019091015463ffffffff9091169082565b612a2e612cc6565b6001600160a01b0316612a3f612115565b6001600160a01b031614612a655760405162461bcd60e51b8152600401610e9190615411565b6001600160a01b038116612a8b5760405162461bcd60e51b8152600401610e919061521e565b610f8281613650565b612a9f600033612124565b612abb5760405162461bcd60e51b8152600401610e91906150bf565b6001600160a01b0381166000908152600d602052604090205460ff1615612af45760405162461bcd60e51b8152600401610e91906150f6565b6001600160a01b03166000908152600d60205260409020805460ff19166001179055565b612b23600033612124565b612b3f5760405162461bcd60e51b8152600401610e91906151e7565b6040516370a0823160e01b815282906001600160a01b038516906370a0823190612b6d903090600401614ed4565b60206040518083038186803b158015612b8557600080fd5b505afa158015612b99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbd9190614df3565b1015612c42576040516370a0823160e01b81526001600160a01b038416906370a0823190612bef903090600401614ed4565b60206040518083038186803b158015612c0757600080fd5b505afa158015612c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3f9190614df3565b91505b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061264a9084908690600401614f26565b600061249c82846158ac565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f01ffc9a70000000000000000000000000000000000000000000000000000000014919050565b3390565b6001600160a01b038316612cf05760405162461bcd60e51b8152600401610e919061518a565b6001600160a01b038216612d165760405162461bcd60e51b8152600401610e919061564e565b6001600160a01b038084166000818152600b602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612d71908590614f7c565b60405180910390a3505050565b60005b601454811015610f82576000818152601260205260409020546001600160a01b031663d32b9604612db0611c20565b6040518263ffffffff1660e01b8152600401612dcc9190614f7c565b602060405180830381600087803b158015612de657600080fd5b505af1158015612dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1e9190614cd7565b5080612e29816159c1565b915050612d81565b6001600160a01b038316612e575760405162461bcd60e51b8152600401610e919061512d565b6001600160a01b038216612e7d5760405162461bcd60e51b8152600401610e91906154a3565b60008111612e9d5760405162461bcd60e51b8152600401610e9190615446565b6001600160a01b0382166000908152600d602052604090205460ff1615612ec357600080fd5b612ece83838361328c565b612ed78161398e565b15612ee457612ee4613a7c565b6001600160a01b0382166000908152600e602052604090205460ff1615612f36576001600160a01b0383166000908152600c6020526040812054612f289083612c70565b9050612f348482613ab8565b505b6001600160a01b0383166000908152600e602052604090205460ff1615612f88576001600160a01b0382166000908152600c6020526040812054612f7a9083613063565b9050612f868382613ab8565b505b6001600160a01b03821660009081526015602052604081205460ff168015612fbe57506039546001600160a01b03858116911614155b8015612fd05750612fce84611680565b155b15612fdd5750600161302b565b6001600160a01b03841660009081526011602052604090205460ff16156130065750600261302b565b6001600160a01b03831660009081526011602052604090205460ff161561302b575060035b6120c684848484613b6e565b6000818484111561305b5760405162461bcd60e51b8152600401610e919190614feb565b505050900390565b600061249c8284615942565b6130798282612124565b61113e57613091816001600160a01b03166014613eef565b61309c836020613eef565b6040516020016130ad929190614e53565b60408051601f198184030181529082905262461bcd60e51b8252610e9191600401614feb565b6130dd8282612124565b61113e5760008281526001602081815260408084206001600160a01b0386168552909152909120805460ff19169091179055613117612cc6565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6131658282612124565b1561113e5760008281526001602090815260408083206001600160a01b03851684529091529020805460ff1916905561319c612cc6565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600080600084116132035760405162461bcd60e51b8152600401610e91906155ba565b61320b6138e2565b84111561322a5760405162461bcd60e51b8152600401610e919061501e565b600061323684866140e6565b845490915081141561324f576000809250925050613285565b600184600101828154811061327457634e487b7160e01b600052603260045260246000fd5b906000526020600020015492509250505b9250929050565b6132978383836110dd565b6001600160a01b0383166132bb576132ae826141c5565b6132b6614200565b6110dd565b6001600160a01b0382166132d2576132ae836141c5565b6132db836141c5565b6110dd826141c5565b6001600160a01b03821661330a5760405162461bcd60e51b8152600401610e91906153da565b600f546133179082612c70565b600f556001600160a01b0382166000908152600a602052604090205461333d9082612c70565b6001600160a01b0383166000818152600a60205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061338c908590614f7c565b60405180910390a35050565b816001600160a01b0316836001600160a01b0316141580156133ba5750600081115b156110dd576001600160a01b0383161561345d576001600160a01b0383166000908152603e602052604081205463ffffffff1690816133fa57600061343d565b6001600160a01b0385166000908152603d602052604081209061341e600185615959565b63ffffffff1663ffffffff168152602001908152602001600020600101545b9050600061344b8285613063565b90506134598684848461420d565b5050505b6001600160a01b038216156110dd576001600160a01b0382166000908152603e602052604081205463ffffffff1690816134985760006134db565b6001600160a01b0384166000908152603d60205260408120906134bc600185615959565b63ffffffff1663ffffffff168152602001908152602001600020600101545b905060006134e98285612c70565b90506128758584848461420d565b6001600160a01b03821661351d5760405162461bcd60e51b8152600401610e9190615500565b61355a81604051806060016040528060228152602001615aaf602291396001600160a01b0385166000908152600a60205260409020549190613037565b6001600160a01b0383166000908152600a6020526040902055600f546135809082613063565b600f556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061338c908590614f7c565b6001600160a01b038083166000908152603c6020526040812054909116906135e8846118a7565b6001600160a01b038581166000818152603c602052604080822080546001600160a01b031916898616908117909155905194955093928616927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46120c6828483613398565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006136ac84846128de565b905060001981146120c657818110156136d75760405162461bcd60e51b8152600401610e919061527b565b6120c68484848403612cca565b60008060145460016136f691906158ac565b905060005b60145481101561373d576000818152601360205260409020546001600160a01b038581169116141561372b578091505b80613735816159c1565b9150506136fb565b5092915050565b604080516002808252606082018352600092602083019080368337019050509050818160008151811061378757634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152603b548251911690829060019081106137c657634e487b7160e01b600052603260045260246000fd5b6001600160a01b03928316602091820292909201015260395460405163095ea7b360e01b81528483169263095ea7b392613807929116908790600401614f26565b602060405180830381600087803b15801561382157600080fd5b505af1158015613835573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138599190614cd7565b50603954604051635c11d79560e01b81526001600160a01b0390911690635c11d795906138939086906000908690309042906004016157f9565b600060405180830381600087803b1580156138ad57600080fd5b505af11580156138c1573d6000803e3d6000fd5b50505050505050565b600061249c8284615923565b600061249c82846158ec565b600061109660406143ae565b60006138fa60406143b2565b60006139046138e2565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67816040516139359190614f7c565b60405180910390a1905090565b600080805b60145481101561373d576000818152601260205260409020546001600160a01b038581169116141561397857600191505b80613982816159c1565b915050613947565b4690565b603a546000906001600160a01b031633148015906139b65750603b54600160a81b900460ff16155b80156139c4575060325460ff165b80156139df575060365460375443916139dc916158ac565b11155b8015613a6c5750603554603b546040516370a0823160e01b81526001600160a01b03909116906370a0823190613a19903090600401614ed4565b60206040518083038186803b158015613a3157600080fd5b505afa158015613a45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a699190614df3565b10155b8015610dfe575050603854111590565b603554613a8b9061dead6143bb565b43603755603554603454613a9e91612c70565b6034819055603354101561190b576032805460ff19169055565b600081118015613ade57506001600160a01b0382166000908152600c6020526040902054155b15613af157613aec82614574565b613b24565b80158015613b1657506001600160a01b0382166000908152600c602052604090205415155b15613b2457613b24826145d5565b6001600160a01b0382166000908152600c6020526040902054600954613b4f918391610f2c91613063565b6009556001600160a01b039091166000908152600c6020526040902055565b60ff8116613b8357613b7e614722565b613bbf565b8060ff1660011415613b9757613b7e61477c565b8060ff1660021415613bab57613b7e6147d6565b8060ff1660031415613bbf57613bbf614830565b6000613bca8361488a565b9050613c3b836040518060400160405280601481526020017f496e73756666696369656e742042616c616e6365000000000000000000000000815250600a6000896001600160a01b03166001600160a01b03168152602001908152602001600020546130379092919063ffffffff16565b6001600160a01b038087166000908152600a602052604080822093909355835191871681529190912054613c6e91612c70565b6001600160a01b0385166000908152600a6020526040902055613c9081614911565b836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360000151604051613cd79190614f7c565b60405180910390a36001600160a01b038581166000908152603c602052604090205416613d28576001600160a01b0385166000818152603c6020526040902080546001600160a01b03191690911790555b6001600160a01b038481166000908152603c602052604090205416613d71576001600160a01b0384166000818152603c6020526040902080546001600160a01b03191690911790555b8051831415613db1576001600160a01b038086166000908152603c6020526040808220548784168352912054613dac92918216911685613398565b613e53565b6001600160a01b038086166000908152603c60205260408082205487841683529120548351613de893928316929190911690613398565b6001600160a01b038086166000908152603c60209081526040808320546019548516845292205490840151613e2593928316929190911690613398565b6001600160a01b038086166000908152603c60205260408120546060840151613e5393919091169190613398565b60ff82161580613e6657508160ff166001145b15613e7857613e73614939565b6120c4565b8160ff1660021480613e8d57508160ff166003145b156120c457613e9a614939565b60195460208201516040516001600160a01b03928316928816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91613ee09190614f7c565b60405180910390a35050505050565b60606000613efe836002615923565b613f099060026158ac565b67ffffffffffffffff811115613f2f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613f59576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613f9e57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613ff757634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600061401b846002615923565b6140269060016158ac565b90505b60018111156140c7577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061407557634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061409957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c936140c0816159aa565b9050614029565b50831561249c5760405162461bcd60e51b8152600401610e919061508a565b81546000906140f757506000610e64565b82546000905b80821015614161576000614111838361496f565b90508486828154811061413457634e487b7160e01b600052603260045260246000fd5b9060005260206000200154111561414d5780915061415b565b6141588160016158ac565b92505b506140fd565b6000821180156141a457508385614179600185615942565b8154811061419757634e487b7160e01b600052603260045260246000fd5b9060005260206000200154145b156141bd576141b4600183615942565b92505050610e64565b509050610e64565b6001600160a01b0381166000908152604160209081526040808320600c90925290912054610f8291906141fb90610f2c856118a7565b61498a565b61190b60426141fb610ec6565b600061423143604051806060016040528060368152602001615a54603691396149d4565b905060008463ffffffff1611801561428b57506001600160a01b0385166000908152603d6020526040812063ffffffff83169161426f600188615959565b63ffffffff908116825260208201929092526040016000205416145b156142d4576001600160a01b0385166000908152603d6020526040812083916142b5600188615959565b63ffffffff168152602081019190915260400160002060010155614364565b60408051808201825263ffffffff838116825260208083018681526001600160a01b038a166000908152603d83528581208a851682529092529390209151825463ffffffff1916911617815590516001918201556143339085906158c4565b6001600160a01b0386166000908152603e60205260409020805463ffffffff191663ffffffff929092169190911790555b846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724848460405161439f929190615869565b60405180910390a25050505050565b5490565b80546001019055565b603b805460ff60a81b1916600160a81b1790556040805160028082526060820183526000926020830190803683375050603b5482519293506001600160a01b03169183915060009061441d57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050308160018151811061445f57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152603b5460395460405163095ea7b360e01b81529183169263095ea7b3926144a492909116908790600401614f26565b602060405180830381600087803b1580156144be57600080fd5b505af11580156144d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144f69190614cd7565b50603954604051635c11d79560e01b81526001600160a01b0390911690635c11d795906145309086906000908690889042906004016157f9565b600060405180830381600087803b15801561454a57600080fd5b505af115801561455e573d6000803e3d6000fd5b5050603b805460ff60a81b191690555050505050565b600780546001600160a01b039092166000818152600860205260408120849055600184018355919091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68890910180546001600160a01b0319169091179055565b600780546145e590600190615942565b8154811061460357634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b038481168452600890925260409092205460078054929093169291811061464f57634e487b7160e01b600052603260045260246000fd5b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905591831681526008918290526040812054600780549193929161469b90600190615942565b815481106146b957634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b0316835282019290925260400190205560078054806146fd57634e487b7160e01b600052603160045260246000fd5b600082815260209020810160001990810180546001600160a01b031916905501905550565b60168054601e5560178054601f556018805460205560198054602180546001600160a01b038084166001600160a01b0319928316179092556022549096556023549094556024549092556025549092169216919091179055565b60168054601e5560178054601f556018805460205560198054602180546001600160a01b038084166001600160a01b0319928316179092556026549096556027549094556028549092556029549092169216919091179055565b60168054601e5560178054601f556018805460205560198054602180546001600160a01b038084166001600160a01b031992831617909255602a54909655602b54909455602c54909255602d549092169216919091179055565b60168054601e5560178054601f556018805460205560198054602180546001600160a01b038084166001600160a01b031992831617909255602e54909655602f549094556030549092556031549092169216919091179055565b614892614b12565b60006040518060800160405280600081526020016148b585601660000154614a04565b81526020016148c985601660010154614a04565b81526020016148dd85601660020154614a04565b81525090506149098160600151611090836040015161109085602001518861306390919063ffffffff16565b815292915050565b602081015160195461492c91906001600160a01b0316614a23565b610f828160600151614a80565b601e54601655601f54601755602054601855602154601980546001600160a01b0319166001600160a01b03909216919091179055565b600061497e60028484186158ec565b61249c908484166158ac565b60006149946138e2565b9050806149a084614ac1565b10156110dd578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b60008164010000000084106149fc5760405162461bcd60e51b8152600401610e919190614feb565b509192915050565b600081614a1357506000610e64565b61249c612710611f7585856138ca565b6001600160a01b038116614a365761113e565b81614a405761113e565b6001600160a01b0381166000908152600a6020526040902054614a639083612c70565b6001600160a01b0382166000908152600a60205260409020555050565b80614a8a57610f82565b306000908152600a6020526040902054614aa49082612c70565b306000818152600a6020526040902091909155610f8290826134f7565b8054600090614ad257506000610e01565b81548290614ae290600190615942565b81548110614b0057634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050610e01565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b600060208284031215614b4b578081fd5b813561249c81615a08565b600060208284031215614b67578081fd5b815161249c81615a08565b60008060408385031215614b84578081fd5b8235614b8f81615a08565b91506020830135614b9f81615a08565b809150509250929050565b600080600060608486031215614bbe578081fd5b8335614bc981615a08565b92506020840135614bd981615a08565b929592945050506040919091013590565b60008060408385031215614bfc578182fd5b8235614c0781615a08565b91506020830135614b9f81615a1d565b60008060408385031215614c29578182fd5b8235614c3481615a08565b946020939093013593505050565b60008060008060008060c08789031215614c5a578182fd5b8635614c6581615a08565b95506020870135945060408701359350606087013560ff81168114614c88578283fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215614cb4578182fd5b8235614cbf81615a08565b9150602083013563ffffffff81168114614b9f578182fd5b600060208284031215614ce8578081fd5b815161249c81615a1d565b600080600080600060a08688031215614d0a578081fd5b8535614d1581615a1d565b97602087013597506040870135966060810135965060800135945092505050565b600060208284031215614d47578081fd5b5035919050565b60008060408385031215614d60578081fd5b823591506020830135614b9f81615a08565b600060208284031215614d83578081fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461249c578182fd5b600080600060608486031215614dc6578081fd5b8335614dd181615a08565b9250602084013591506040840135614de881615a08565b809150509250925092565b600060208284031215614e04578081fd5b5051919050565b60008060408385031215614d60578182fd5b7f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b60007f416363657373436f6e74726f6c3a206163636f756e742000000000000000000082528351614e8b81601785016020880161597e565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614ec881602884016020880161597e565b01602801949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b9615158752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b90815260200190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b93845260ff9290921660208401526040830152606082015260800190565b600060208252825180602084015261500a81604085016020870161597e565b601f01601f19169190910160400192915050565b6020808252601d908201527f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000604082015260600190565b6020808252818101527f5059453a2041646472657373205a65726f206973206e6f7420616c6c6f776564604082015260600190565b6020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b60208082526011908201527f4655454c3a204e4f545f414c4c4f574544000000000000000000000000000000604082015260600190565b6020808252601f908201527f4164647265737320697320616c726561647920626c61636b6c69737465642100604082015260600190565b60208082526025908201527f42455032303a207472616e736665722066726f6d20746865207a65726f20616460408201527f6472657373000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f42455032303a20617070726f76652066726f6d20746865207a65726f2061646460408201527f7265737300000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526013908201527f4348455252593a204e4f545f414c4c4f57454400000000000000000000000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201527f6464726573730000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604082015260600190565b6020808252604c908201527f4164647265737320686173206e6f74206265656e20626c61636b6c697374656460408201527f2120456e74657220616e20616464726573732074686174206973206f6e20746860608201527f6520626c61636b6c6973742e0000000000000000000000000000000000000000608082015260a00190565b60208082526010908201527f5059453a204e4f545f414c4c4f57454400000000000000000000000000000000604082015260600190565b6020808252601a908201527f4348455252593a20524541434845445f4d41585f535550504c59000000000000604082015260600190565b60208082526016908201527f4665657320657863656564206d6178206c696d69742e00000000000000000000604082015260600190565b6020808252601f908201527f42455032303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f5472616e7366657220616d6f756e74206d75737420626520677265617465722060408201527f7468616e207a65726f0000000000000000000000000000000000000000000000606082015260800190565b60208082526023908201527f42455032303a207472616e7366657220746f20746865207a65726f206164647260408201527f6573730000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f42455032303a206275726e2066726f6d20746865207a65726f2061646472657360408201527f7300000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4348455252593a3a64656c656761746542795369673a20696e76616c6964206e60408201527f6f6e636500000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526016908201527f4552433230536e617073686f743a206964206973203000000000000000000000604082015260600190565b60208082526028908201527f4348455252593a3a64656c656761746542795369673a20696e76616c6964207360408201527f69676e6174757265000000000000000000000000000000000000000000000000606082015260800190565b60208082526022908201527f42455032303a20617070726f766520746f20746865207a65726f20616464726560408201527f7373000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f4348455252593a3a6765745072696f72566f7465733a206e6f7420796574206460408201527f657465726d696e65640000000000000000000000000000000000000000000000606082015260800190565b60208082526012908201527f4150504c453a204e4f545f414c4c4f5745440000000000000000000000000000604082015260600190565b60208082526028908201527f4348455252593a3a64656c656761746542795369673a207369676e617475726560408201527f2065787069726564000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560408201527f20726f6c657320666f722073656c660000000000000000000000000000000000606082015260800190565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b818110156158485784516001600160a01b031683529383019391830191600101615823565b50506001600160a01b03969096166060850152505050608001529392505050565b918252602082015260400190565b63ffffffff91909116815260200190565b63ffffffff929092168252602082015260400190565b60ff91909116815260200190565b600082198211156158bf576158bf6159dc565b500190565b600063ffffffff8083168185168083038211156158e3576158e36159dc565b01949350505050565b6000826158fb576158fb6159f2565b500490565b600063ffffffff80841680615917576159176159f2565b92169190910492915050565b600081600019048311821515161561593d5761593d6159dc565b500290565b600082821015615954576159546159dc565b500390565b600063ffffffff83811690831681811015615976576159766159dc565b039392505050565b60005b83811015615999578181015183820152602001615981565b838111156120c65750506000910152565b6000816159b9576159b96159dc565b506000190190565b60006000198214156159d5576159d56159dc565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b0381168114610f8257600080fd5b8015158114610f8257600080fdfe42455032303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654348455252593a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d6265722065786365656473203332206269747342455032303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f42455032303a206275726e20616d6f756e7420657863656564732062616c616e6365a26469706673582212207d80752e756f0d892146cef769378108ea493345c6c5342c3d7921f068e687f664736f6c63430008010033

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

0000000000000000000000004f71e29c3d5934a15308005b19ca263061e99616000000000000000000000000c71b2b3dd4a0a72f8857e4f5fbac53b401f2735500000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000003e8

-----Decoded View---------------
Arg [0] : _router (address): 0x4F71E29C3D5934A15308005B19Ca263061E99616
Arg [1] : _development (address): 0xC71B2b3DD4a0A72f8857e4f5fBac53b401F27355
Arg [2] : _developmentFee (uint256): 200
Arg [3] : _buybackFee (uint256): 200
Arg [4] : _burnFee (uint256): 1000

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000004f71e29c3d5934a15308005b19ca263061e99616
Arg [1] : 000000000000000000000000c71b2b3dd4a0a72f8857e4f5fbac53b401f27355
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c8
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000c8
Arg [4] : 00000000000000000000000000000000000000000000000000000000000003e8


Deployed Bytecode Sourcemap

77495:40690:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52630:204;;;;;;;;;;-1:-1:-1;52630:204:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80255:35;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;84217:92::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;85172:161::-;;;;;;;;;;-1:-1:-1;85172:161:0;;;;;:::i;:::-;;:::i;99304:574::-;;;;;;;;;;-1:-1:-1;99304:574:0;;;;;:::i;:::-;;:::i;:::-;;84521:95;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;87780:612::-;;;;;;;;;;-1:-1:-1;87780:612:0;;;;;:::i;:::-;;:::i;81500:122::-;;;;;;;;;;;;;:::i;85341:313::-;;;;;;;;;;-1:-1:-1;85341:313:0;;;;;:::i;:::-;;:::i;54057:131::-;;;;;;;;;;-1:-1:-1;54057:131:0;;;;;:::i;:::-;;:::i;77696:62::-;;;;;;;;;;;;;:::i;93166:151::-;;;;;;;;;;;;;:::i;80222:24::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;54450:147::-;;;;;;;;;;-1:-1:-1;54450:147:0;;;;;:::i;:::-;;:::i;79761:47::-;;;;;;;;;;-1:-1:-1;79761:47:0;;;;;:::i;:::-;;:::i;84421:92::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;55498:218::-;;;;;;;;;;-1:-1:-1;55498:218:0;;;;;:::i;:::-;;:::i;85662:227::-;;;;;;;;;;-1:-1:-1;85662:227:0;;;;;:::i;:::-;;:::i;115609:301::-;;;;;;;;;;-1:-1:-1;115609:301:0;;;;;:::i;:::-;;:::i;86564:184::-;;;;;;;;;;-1:-1:-1;86564:184:0;;;;;:::i;:::-;;:::i;89291:552::-;;;;;;;;;;-1:-1:-1;89291:552:0;;;;;:::i;:::-;;:::i;104707:473::-;;;;;;;;;;-1:-1:-1;104707:473:0;;;;;:::i;:::-;;:::i;103729:407::-;;;;;;;;;;-1:-1:-1;103729:407:0;;;;;:::i;:::-;;:::i;86183:183::-;;;;;;;;;;-1:-1:-1;86183:183:0;;;;;:::i;:::-;;:::i;91218:123::-;;;;;;;;;;-1:-1:-1;91218:123:0;;;;;:::i;:::-;;:::i;113853:335::-;;;;;;;;;;-1:-1:-1;113853:335:0;;;;;:::i;:::-;;:::i;80949:45::-;;;;;;;;;;-1:-1:-1;80949:45:0;;;;;:::i;:::-;;:::i;105736:104::-;;;;;;;;;;-1:-1:-1;105736:104:0;;;;;:::i;:::-;;:::i;88400:470::-;;;;;;;;;;-1:-1:-1;88400:470:0;;;;;:::i;:::-;;:::i;112106:147::-;;;;;;;;;;-1:-1:-1;112106:147:0;;;;;:::i;:::-;;:::i;80446:30::-;;;;;;;;;;;;;:::i;113076:200::-;;;;;;;;;;-1:-1:-1;113076:200:0;;;;;:::i;:::-;;:::i;81378:49::-;;;;;;;;;;-1:-1:-1;81378:49:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;84719:119::-;;;;;;;;;;-1:-1:-1;84719:119:0;;;;;:::i;:::-;;:::i;59328:103::-;;;;;;;;;;;;;:::i;108341:1243::-;;;;;;;;;;-1:-1:-1;108341:1243:0;;;;;:::i;:::-;;:::i;80022:28::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;104149:452::-;;;;;;;;;;-1:-1:-1;104149:452:0;;;;;:::i;:::-;;:::i;93325:189::-;;;;;;;;;;;;;:::i;81914:39::-;;;;;;;;;;-1:-1:-1;81914:39:0;;;;;:::i;:::-;;:::i;77998:26::-;;;;;;;;;;;;;:::i;95891:1463::-;;;;;;;;;;-1:-1:-1;95891:1463:0;;;;;:::i;:::-;;:::i;115427:121::-;;;;;;;;;;;;;:::i;58677:87::-;;;;;;;;;;;;;:::i;52926:147::-;;;;;;;;;;-1:-1:-1;52926:147:0;;;;;:::i;:::-;;:::i;84317:96::-;;;;;;;;;;;;;:::i;114986:67::-;;;;;;;;;;;;;:::i;115918:234::-;;;;;;;;;;-1:-1:-1;115918:234:0;;;;;:::i;:::-;;:::i;78637:41::-;;;;;;;;;;-1:-1:-1;78637:41:0;;;;;:::i;:::-;;:::i;101103:187::-;;;;;;;;;;-1:-1:-1;101103:187:0;;;;;:::i;:::-;;:::i;52017:49::-;;;;;;;;;;;;;:::i;85897:278::-;;;;;;;;;;-1:-1:-1;85897:278:0;;;;;:::i;:::-;;:::i;84846:167::-;;;;;;;;;;-1:-1:-1;84846:167:0;;;;;:::i;:::-;;:::i;80330:19::-;;;;;;;;;;;;;:::i;87184:588::-;;;;;;;;;;-1:-1:-1;87184:588:0;;;;;:::i;:::-;;:::i;88878:401::-;;;;;;;;;;-1:-1:-1;88878:401:0;;;;;:::i;:::-;;:::i;107667:243::-;;;;;;;;;;-1:-1:-1;107667:243:0;;;;;:::i;:::-;;:::i;100152:639::-;;;;;;;;;;-1:-1:-1;100152:639:0;;;;;:::i;:::-;;:::i;80356:81::-;;;;;;;;;;;;;:::i;106274:1192::-;;;;;;;;;;-1:-1:-1;106274:1192:0;;;;;:::i;:::-;;:::i;80297:26::-;;;;;;;;;;;;;:::i;77627:62::-;;;;;;;;;;;;;:::i;54842:149::-;;;;;;;;;;-1:-1:-1;54842:149:0;;;;;:::i;:::-;;:::i;84624:87::-;;;;;;;;;;;;;:::i;85021:143::-;;;;;;;;;;-1:-1:-1;85021:143:0;;;;;:::i;:::-;;:::i;79991:24::-;;;;;;;;;;;;;:::i;86756:188::-;;;;;;;;;;-1:-1:-1;86756:188:0;;;;;:::i;:::-;;:::i;81716:117::-;;;;;;;;;;;;;:::i;77765:70::-;;;;;;;;;;;;;:::i;86374:182::-;;;;;;;;;;-1:-1:-1;86374:182:0;;;;;:::i;:::-;;:::i;81239:70::-;;;;;;;;;;-1:-1:-1;81239:70:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;59586:201::-;;;;;;;;;;-1:-1:-1;59586:201:0;;;;;:::i;:::-;;:::i;113483:296::-;;;;;;;;;;-1:-1:-1;113483:296:0;;;;;:::i;:::-;;:::i;101350:321::-;;;;;;;;;;-1:-1:-1;101350:321:0;;;;;:::i;:::-;;:::i;52630:204::-;52715:4;52739:47;;;52754:32;52739:47;;:87;;;52790:36;52814:11;52790:23;:36::i;:::-;52732:94;;52630:204;;;;:::o;80255:35::-;;;-1:-1:-1;;;;;80255:35:0;;:::o;84217:92::-;84296:5;;;;;;;;;;;;;;;;;84217:92;:::o;85172:161::-;85247:4;85264:39;85273:12;:10;:12::i;:::-;85287:7;85296:6;85264:8;:39::i;:::-;-1:-1:-1;85321:4:0;85172:161;;;;;:::o;99304:574::-;99454:39;52062:4;99482:10;99454:7;:39::i;:::-;99446:71;;;;-1:-1:-1;;;99446:71:0;;;;;;;:::i;:::-;;;;;;;;;99528:8;:38;;-1:-1:-1;;99528:38:0;;;;;;;;;;;99577:23;:30;;;;-1:-1:-1;99618:31:0;:35;99664:26;:36;99711:31;:41;99795:12;99763:29;:44;99818:32;:52;99304:574::o;84521:95::-;84601:7;;84521:95;:::o;87780:612::-;87864:36;77807:28;87889:10;87864:7;:36::i;:::-;87856:68;;;;-1:-1:-1;;;87856:68:0;;;;;;;:::i;:::-;87975:24;;87943:27;;88025:4;;87943:78;;88005:15;;87943:57;;:27;:31;:57::i;:::-;:61;;:78::i;:::-;:86;;87935:121;;;;-1:-1:-1;;;87935:121:0;;;;;;;:::i;:::-;88067:12;:45;;;88123:16;:49;;;88216:26;;:47;;88097:15;88216:30;:47::i;:::-;88183:15;:80;88308:27;;:48;;88340:15;88308:31;:48::i;:::-;88274:16;:82;88367:17;:15;:17::i;:::-;87780:612;:::o;81500:122::-;81542:80;81500:122;:::o;85341:313::-;85439:4;85456:36;85466:6;85474:9;85485:6;85456:9;:36::i;:::-;85503:121;85512:6;85520:12;:10;:12::i;:::-;85534:89;85572:6;85534:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;85534:19:0;;;;;;:11;:19;;;;;;85554:12;:10;:12::i;:::-;-1:-1:-1;;;;;85534:33:0;;;;;;;;;;;;-1:-1:-1;85534:33:0;;;:89;:37;:89::i;:::-;85503:8;:121::i;:::-;-1:-1:-1;85642:4:0;85341:313;;;;;:::o;54057:131::-;54131:7;54158:12;;;:6;:12;;;;;;;;:22;;;54057:131::o;77696:62::-;77734:24;77696:62;:::o;93166:151::-;93219:7;93246:63;93287:21;93305:1;93287:9;:21::i;:::-;93246:36;93258:23;80395:42;93258:9;:23::i;:::-;93246:7;;;:11;:36::i;:::-;:40;;:63::i;:::-;93239:70;;93166:151;:::o;80222:24::-;;;;;;;;;;;;;;;;;;;;;:::o;54450:147::-;54533:18;54546:4;54533:12;:18::i;:::-;52508:30;52519:4;52525:12;:10;:12::i;:::-;52508:10;:30::i;:::-;54564:25:::1;54575:4;54581:7;54564:10;:25::i;:::-;54450:147:::0;;;:::o;79761:47::-;;;;;;;;;;;;;;;:::o;84421:92::-;79980:2;84421:92;:::o;55498:218::-;55605:12;:10;:12::i;:::-;-1:-1:-1;;;;;55594:23:0;:7;-1:-1:-1;;;;;55594:23:0;;55586:83;;;;-1:-1:-1;;;55586:83:0;;;;;;;:::i;:::-;55682:26;55694:4;55700:7;55682:11;:26::i;:::-;55498:218;;:::o;85662:227::-;85759:4;85776:83;85785:12;:10;:12::i;:::-;85799:7;85808:50;85847:10;85808:11;:25;85820:12;:10;:12::i;:::-;-1:-1:-1;;;;;85808:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;85808:25:0;;;:34;;;;;;;;;;;:38;:50::i;115609:301::-;-1:-1:-1;;;;;115778:33:0;;115701:7;115778:33;;;:24;:33;;;;;115701:7;;;;115757:55;;115766:10;;115757:8;:55::i;:::-;115721:91;;;;115832:11;:70;;-1:-1:-1;;;;;115878:15:0;;;;;;:6;:15;;;;;:22;115855:46;;:18;115885:7;115855:9;:18::i;:46::-;115832:70;;;115846:5;115832:70;115825:77;115609:301;-1:-1:-1;;;;;115609:301:0:o;86564:184::-;86635:39;52062:4;86663:10;86635:7;:39::i;:::-;86627:71;;;;-1:-1:-1;;;86627:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;86709:24:0;;;;;:15;:24;;;;;:31;;-1:-1:-1;;86709:31:0;86736:4;86709:31;;;86564:184::o;89291:552::-;89378:39;52062:4;89406:10;89378:7;:39::i;:::-;89370:71;;;;-1:-1:-1;;;89370:71:0;;;;;;;:::i;:::-;89471:11;;;-1:-1:-1;;;;;89471:11:0;;;89486:5;89452:31;;;:18;:31;;;;;;;;;:39;;-1:-1:-1;;89452:39:0;;;89502:13;:39;;-1:-1:-1;;;;;;89502:39:0;;;;;;;;;;;89552:19;;;;;;;;;;89589:20;;;;;;;:13;;;;;:18;;:20;;;;;89452:31;;89589:20;;;;;;:13;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89582:4;:27;;-1:-1:-1;;;;;;89582:27:0;;;-1:-1:-1;;;;;89582:27:0;;;;;;89637:11;;;;;-1:-1:-1;89622:27:0;;;:14;:27;;;;;;;;:34;;-1:-1:-1;;89622:34:0;;;-1:-1:-1;89622:34:0;;;;;;89686:11;;;;89667:31;;:18;:31;;;;;:38;;;;;;;;89729:11;;89718:8;;;;:22;;89729:11;;;89718:22;;;;;;;89763:4;;89751:6;:9;;;;:16;;89763:4;;;;89751:16;;;;;;89780:40;89821:13;:11;:13::i;:::-;89780:55;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;104707:473::-;104777:32;77665:24;104798:10;104777:7;:32::i;:::-;104769:64;;;;-1:-1:-1;;;104769:64:0;;;;;;;:::i;:::-;78935:18;104852:26;104870:7;104852:13;:11;:13::i;:26::-;:40;;104844:79;;;;-1:-1:-1;;;104844:79:0;;;;;;;:::i;:::-;104934:46;104963:1;104967:3;104972:7;104934:20;:46::i;:::-;104991:19;104997:3;105002:7;104991:5;:19::i;:::-;-1:-1:-1;;;;;105034:14:0;;;105060:1;105034:14;;;:9;:14;;;;;;;105031:80;;-1:-1:-1;;;;;105079:14:0;;;;;;:9;:14;;;;;:20;;-1:-1:-1;;;;;;105079:20:0;;;;;;105031:80;-1:-1:-1;;;;;105148:14:0;;;105144:1;105148:14;;;:9;:14;;;;;;105121:51;;105148:14;105164:7;105121:14;:51::i;103729:407::-;103787:32;77734:24;103808:10;103787:7;:32::i;:::-;103779:62;;;;-1:-1:-1;;;103779:62:0;;;;;;;:::i;:::-;103853:53;103874:10;103894:1;103898:7;103853:20;:53::i;:::-;103917:26;103923:10;103935:7;103917:5;:26::i;:::-;103968:10;103991:1;103958:21;;;:9;:21;;;;;;-1:-1:-1;;;;;103958:21:0;103955:103;;104035:10;104011:21;;;;:9;:21;;;;;:34;;-1:-1:-1;;;;;;104011:34:0;;;;;;103955:103;104094:10;104084:21;;;;:9;:21;;;;;;104069:58;;-1:-1:-1;;;;;104084:21:0;;;;104119:7;104069:14;:58::i;86183:183::-;86250:39;52062:4;86278:10;86250:7;:39::i;:::-;86242:71;;;;-1:-1:-1;;;86242:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;86324:27:0;;;;;:18;:27;;;;;:34;;-1:-1:-1;;86324:34:0;86354:4;86324:34;;;86183:183::o;91218:123::-;-1:-1:-1;;;;;91306:27:0;91282:4;91306:27;;;:18;:27;;;;;;;;;91218:123::o;113853:335::-;113936:39;52062:4;113964:10;113936:7;:39::i;:::-;113928:69;;;;-1:-1:-1;;;113928:69:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;114017:30:0;;;;;;:13;:30;;;;;;;;114009:120;;;;-1:-1:-1;;;114009:120:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;114141:30:0;114174:5;114141:30;;;:13;:30;;;;;:38;;-1:-1:-1;;114141:38:0;;;113853:335::o;80949:45::-;;;;;;;;;;;;-1:-1:-1;;;;;80949:45:0;;:::o;105736:104::-;105800:32;105810:10;105822:9;105800;:32::i;88400:470::-;88481:36;77807:28;88506:10;88481:7;:36::i;:::-;88473:68;;;;-1:-1:-1;;;88473:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;88560:26:0;;88552:71;;;;-1:-1:-1;;;88552:71:0;;;;;;;:::i;:::-;88634:31;:46;;-1:-1:-1;;;;;88634:46:0;;;-1:-1:-1;;;;;;88634:46:0;;;;;;;;88691:35;:50;;;;;;;;88752:34;:49;;;;;;;;88812:35;:50;;;;;;;;88400:470::o;112106:147::-;-1:-1:-1;;;;;112225:18:0;;112171:7;112225:18;;;:9;:18;;;;;;;;;112198:6;:15;;;;;:22;:46;;:26;:46::i;80446:30::-;;;;;;;;;:::o;113076:200::-;113162:39;52062:4;113190:10;113162:7;:39::i;:::-;113154:69;;;;-1:-1:-1;;;113154:69:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;113235:26:0;;;;;;;;:17;:26;;;;;:32;;-1:-1:-1;;113235:32:0;;;;;;;;;;113076:200::o;81378:49::-;;;;;;;;;;;;;;;:::o;84719:119::-;-1:-1:-1;;;;;84812:18:0;84785:7;84812:18;;;:9;:18;;;;;;;84719:119::o;59328:103::-;58908:12;:10;:12::i;:::-;-1:-1:-1;;;;;58897:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;58897:23:0;;58889:68;;;;-1:-1:-1;;;58889:68:0;;;;;;;:::i;:::-;59393:30:::1;59420:1;59393:18;:30::i;:::-;59328:103::o:0;108341:1243::-;108437:7;108484:12;108470:11;:26;108462:80;;;;-1:-1:-1;;;108462:80:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;108577:23:0;;108555:19;108577:23;;;:14;:23;;;;;;;;108615:17;108611:58;;108656:1;108649:8;;;;;108611:58;-1:-1:-1;;;;;108729:20:0;;;;;;:11;:20;;;;;108781:11;;108750:16;108765:1;108750:12;:16;:::i;:::-;108729:38;;;;;;;;;;;;;;;-1:-1:-1;108729:38:0;:48;;:63;108725:147;;-1:-1:-1;;;;;108816:20:0;;;;;;:11;:20;;;;;;108837:16;108852:1;108837:12;:16;:::i;:::-;108816:38;;;;;;;;;;;;;;;:44;;;108809:51;;;;;108725:147;-1:-1:-1;;;;;108933:20:0;;;;;;:11;:20;;;;;;;;:23;;;;;;;;:33;:23;:33;:47;-1:-1:-1;108929:88:0;;;109004:1;108997:8;;;;;108929:88;109029:12;;109071:16;109086:1;109071:12;:16;:::i;:::-;109056:31;;109098:428;109113:5;109105:13;;:5;:13;;;109098:428;;;109135:13;109177:1;109160:13;109168:5;109160;:13;:::i;:::-;109159:19;;;;:::i;:::-;109151:27;;:5;:27;:::i;:::-;-1:-1:-1;;;;;109243:20:0;;109220;109243;;;:11;:20;;;;;;;;:28;;;;;;;;;;;;;109220:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;109135:43;;-1:-1:-1;109290:27:0;;109286:229;;;109345:8;;;;-1:-1:-1;109338:15:0;;-1:-1:-1;;;;109338:15:0;109286:229;109379:12;;:26;;;-1:-1:-1;109375:140:0;;;109434:6;109426:14;;109375:140;;;109489:10;109498:1;109489:6;:10;:::i;:::-;109481:18;;109375:140;109098:428;;;;;-1:-1:-1;;;;;;109543:20:0;;;;;;:11;:20;;;;;;;;:27;;;;;;;;;;:33;;;;-1:-1:-1;;108341:1243:0;;;;:::o;80022:28::-;;;;;;;;;-1:-1:-1;;;;;80022:28:0;;:::o;104149:452::-;104226:32;77734:24;104247:10;104226:7;:32::i;:::-;104218:63;;;;-1:-1:-1;;;104218:63:0;;;;;;;:::i;:::-;104293:43;104309:5;104316:10;104328:7;104293:15;:43::i;:::-;104347:48;104368:5;104383:1;104387:7;104347:20;:48::i;:::-;104407:21;104413:5;104420:7;104407:5;:21::i;:::-;-1:-1:-1;;;;;104443:16:0;;;104471:1;104443:16;;;:9;:16;;;;;;;104440:88;;-1:-1:-1;;;;;104491:16:0;;;;;;:9;:16;;;;;:24;;-1:-1:-1;;;;;;104491:24:0;;;;;;104440:88;-1:-1:-1;;;;;104554:16:0;;;;;;;:9;:16;;;;;;104539:53;;104554:16;;104584:7;104539:14;:53::i;93325:189::-;93485:20;;93442:23;;93485:12;93396:27;93369:7;;93396:110;;93485:20;;93396:70;;:45;:70::i;81914:39::-;;;;;;;;;;;;;:::o;77998:26::-;;;;:::o;95891:1463::-;80601:11;80635:6;80631:105;80651:11;;80647:1;:15;80631:105;;;80687:8;;;;:5;:8;;;;;;-1:-1:-1;;;;;80687:8:0;80699:10;80687:22;80684:40;;;80720:4;80711:13;;80684:40;80664:3;;;;:::i;:::-;;;;80631:105;;;-1:-1:-1;80790:13:0;;-1:-1:-1;;;;;80790:13:0;80768:10;:36;;:59;;;80821:6;80768:59;80746:126;;;;-1:-1:-1;;;80746:126:0;;;;;;;:::i;:::-;95975:18:::1;95996:21;96011:5;95996:14;:21::i;:::-;95975:42;;96044:11;;96031:10;:24;96028:1319;;;96093:50;::::0;;;;96072:18:::1;::::0;-1:-1:-1;;;;;96093:23:0;::::1;::::0;::::1;::::0;:50:::1;::::0;96117:10:::1;::::0;96137:4:::1;::::0;96093:50:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96072:71;;96175:6;96161:10;:20;96158:1178;;96202:61;::::0;;;;-1:-1:-1;;;;;96202:26:0;::::1;::::0;::::1;::::0;:61:::1;::::0;96229:10:::1;::::0;96249:4:::1;::::0;96256:6;;96202:61:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;96296:4:0::1;::::0;-1:-1:-1;;;;;96287:13:0;;::::1;96296:4:::0;::::1;96287:13;96284:1037;;96364:4;::::0;96349:46:::1;::::0;-1:-1:-1;;;96349:46:0;;96325:21:::1;::::0;-1:-1:-1;;;;;96364:4:0::1;::::0;96349:31:::1;::::0;:46:::1;::::0;96389:4:::1;::::0;96349:46:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96325:70;;96418:25;96429:6;96437:5;96418:10;:25::i;:::-;96499:4;::::0;96484:46:::1;::::0;-1:-1:-1;;;96484:46:0;;96466:15:::1;::::0;96484:65:::1;::::0;96535:13;;-1:-1:-1;;;;;96499:4:0::1;::::0;96484:31:::1;::::0;:46:::1;::::0;96524:4:::1;::::0;96484:46:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:65::-;96466:83;;96682:16;96701:13;:11;:13::i;:::-;96682:32;;96737:28;96768:54;96813:8;96768:40;96780:12;:27;;;96768:7;:11;;:40;;;;:::i;:::-;:44:::0;::::1;:54::i;:::-;96854:4;::::0;96869:31;;96847:76:::1;::::0;-1:-1:-1;;;96847:76:0;;96737:85;;-1:-1:-1;;;;;;96854:4:0;;::::1;::::0;96847:21:::1;::::0;:76:::1;::::0;96869:31:::1;::::0;96737:85;;96847:76:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;96284:1037;;;;;;;97060:16;97079:13;:11;:13::i;:::-;97060:32;;97115:28;97146:53;97190:8;97146:39;97157:12;:27;;;97146:6;:10;;:39;;;;:::i;:53::-;97247:31:::0;;97224:77:::1;::::0;-1:-1:-1;;;97224:77:0;;97115:84;;-1:-1:-1;;;;;;97224:22:0;;::::1;::::0;::::1;::::0;:77:::1;::::0;97247:31:::1;::::0;97115:84;;97224:77:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;96284:1037;;;96028:1319;;80883:1;95891:1463:::0;;;:::o;115427:121::-;115490:7;58908:12;:10;:12::i;:::-;-1:-1:-1;;;;;58897:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;58897:23:0;;58889:68;;;;-1:-1:-1;;;58889:68:0;;;;;;;:::i;:::-;115517:23:::1;:21;:23::i;58677:87::-:0;58723:7;58750:6;-1:-1:-1;;;;;58750:6:0;58677:87;:::o;52926:147::-;53012:4;53036:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;53036:29:0;;;;;;;;;;;;;;;52926:147::o;84317:96::-;84398:7;;;;;;;;;;;;;;;;;84317:96;:::o;114986:67::-;58908:12;:10;:12::i;:::-;-1:-1:-1;;;;;58897:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;58897:23:0;;58889:68;;;;-1:-1:-1;;;58889:68:0;;;;;;;:::i;:::-;115034:11:::1;:9;:11::i;115918:234::-:0;115990:7;116011:16;116029:13;116046:43;116055:10;116067:21;116046:8;:43::i;:::-;116010:79;;;;116109:11;:35;;116131:13;:11;:13::i;:::-;116109:35;;;116123:5;116109:35;116102:42;115918:234;-1:-1:-1;;;;115918:234:0:o;78637:41::-;;;;;;;;;;;;;:::o;101103:187::-;101178:39;52062:4;101206:10;101178:7;:39::i;:::-;101170:71;;;;-1:-1:-1;;;101170:71:0;;;;;;;:::i;:::-;101252:28;;-1:-1:-1;;;;;101252:20:0;;;:28;;;;;101273:6;;101252:28;;;;101273:6;101252:20;:28;;;;;;;;;;;;;;;;;;;52017:49;52062:4;52017:49;:::o;85897:278::-;85999:4;86016:129;86025:12;:10;:12::i;:::-;86039:7;86048:96;86087:15;86048:96;;;;;;;;;;;;;;;;;:11;:25;86060:12;:10;:12::i;:::-;-1:-1:-1;;;;;86048:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;86048:25:0;;;:34;;;;;;;;;;;:96;:38;:96::i;84846:167::-;84924:4;84941:42;84951:12;:10;:12::i;:::-;84965:9;84976:6;84941:9;:42::i;80330:19::-;;;-1:-1:-1;;;;;80330:19:0;;:::o;87184:588::-;87260:36;77807:28;87285:10;87260:7;:36::i;:::-;87252:68;;;;-1:-1:-1;;;87252:68:0;;;;;;;:::i;:::-;87375:24;;:16;87339:31;87421:4;;87339:78;;87405:11;;87339:61;;:31;:35;:61::i;:78::-;:86;;87331:121;;;;-1:-1:-1;;;87331:121:0;;;;;;;:::i;:::-;87463:23;:37;;;87511:27;:41;;;87596:15;:30;:47;;87489:11;87596:34;:47::i;:::-;87563:15;:80;87688:16;:31;:48;;87724:11;87688:35;:48::i;88878:401::-;88948:36;77807:28;88973:10;88948:7;:36::i;:::-;88940:68;;;;-1:-1:-1;;;88940:68:0;;;;;;;:::i;:::-;89059:16;:31;89027:27;;89109:4;;89027:78;;89096:8;;89027:64;;:27;:31;:64::i;:78::-;:86;;89019:121;;;;-1:-1:-1;;;89019:121:0;;;;;;;:::i;:::-;89151:17;:28;;;89190:24;:35;;;89236:24;:35;88878:401::o;107667:243::-;-1:-1:-1;;;;;107794:23:0;;107747:7;107794:23;;;:14;:23;;;;;;;;107835:16;:67;;107901:1;107835:67;;;-1:-1:-1;;;;;107854:20:0;;;;;;:11;:20;;;;;;107875:16;107890:1;107875:12;:16;:::i;:::-;107854:38;;;;;;;;;;;;;;;:44;;;107835:67;107828:74;107667:243;-1:-1:-1;;;107667:243:0:o;100152:639::-;100236:13;;:23;;;;;;;;100218:15;;-1:-1:-1;;;;;100236:13:0;;:21;;:23;;;;;;;;;;;;;;:13;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100218:41;-1:-1:-1;100292:10:0;-1:-1:-1;;;;;100292:21:0;;;;:74;;-1:-1:-1;100352:13:0;;-1:-1:-1;;;;;100352:13:0;100330:10;:36;100292:74;:118;;;-1:-1:-1;100383:10:0;100405:4;100383:27;100292:118;100270:181;;;;-1:-1:-1;;;100270:181:0;;;;;;;:::i;:::-;100468:27;100489:5;100468:20;:27::i;:::-;100464:320;;-1:-1:-1;;;;;100512:25:0;;;;;;;:18;:25;;;;;;;;:32;;100540:4;-1:-1:-1;;100512:32:0;;;;;;;;100559:14;:21;;;;;:28;;;;;;;;;100610:11;;;100604:18;;:5;:18;;;;;:26;;-1:-1:-1;;;;;;100604:26:0;;;;;;;;100652:11;;100645:19;;:6;:19;;;;;;:28;;;;;;;;;;;;;;;100690:16;;;;100540:4;;100690:16;:::i;:::-;;;;-1:-1:-1;;;;;;;100723:34:0;;;100758:13;:11;:13::i;:::-;100723:49;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;80356:81::-;80395:42;80356:81;:::o;106274:1192::-;106463:23;81542:80;106592:6;:4;:6::i;:::-;106576:24;;;;;;106619:12;:10;:12::i;:::-;106658:4;106513:165;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;106489:200;;;;;;106463:226;;106702:18;81762:71;106814:9;106842:5;106866:6;106747:140;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;106723:175;;;;;;106702:196;;106911:14;107016:15;107050:10;106952:123;;;;;;;;;:::i;:::-;;;;;;;;;;;;;106928:158;;;;;;106911:175;;107099:17;107119:26;107129:6;107137:1;107140;107143;107119:26;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;107119:26:0;;-1:-1:-1;;107119:26:0;;;-1:-1:-1;;;;;;;107164:23:0;;107156:76;;;;-1:-1:-1;;;107156:76:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;107260:17:0;;;;;;:6;:17;;;;;:19;;;;;;:::i;:::-;;;;;107251:5;:28;107243:77;;;;-1:-1:-1;;;107243:77:0;;;;;;;:::i;:::-;107358:6;107339:15;:25;;107331:78;;;;-1:-1:-1;;;107331:78:0;;;;;;;:::i;:::-;107427:31;107437:9;107448;107427;:31::i;:::-;107420:38;;;;106274:1192;;;;;;;:::o;80297:26::-;;;-1:-1:-1;;;;;80297:26:0;;:::o;77627:62::-;77665:24;77627:62;:::o;54842:149::-;54926:18;54939:4;54926:12;:18::i;:::-;52508:30;52519:4;52525:12;:10;:12::i;52508:30::-;54957:26:::1;54969:4;54975:7;54957:11;:26::i;84624:87::-:0;78935:18;84624:87;:::o;85021:143::-;-1:-1:-1;;;;;85129:18:0;;;85102:7;85129:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;85021:143::o;79991:24::-;;;;;;;;;-1:-1:-1;;;;;79991:24:0;;:::o;86756:188::-;86830:39;52062:4;86858:10;86830:7;:39::i;:::-;86822:71;;;;-1:-1:-1;;;86822:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;86904:24:0;86931:5;86904:24;;;:15;:24;;;;;:32;;-1:-1:-1;;86904:32:0;;;86756:188::o;81716:117::-;81762:71;81716:117;:::o;77765:70::-;77807:28;77765:70;:::o;86374:182::-;86439:39;52062:4;86467:10;86439:7;:39::i;:::-;86431:71;;;;-1:-1:-1;;;86431:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;86513:27:0;86543:5;86513:27;;;:18;:27;;;;;:35;;-1:-1:-1;;86513:35:0;;;86374:182::o;81239:70::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;59586:201::-;58908:12;:10;:12::i;:::-;-1:-1:-1;;;;;58897:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;58897:23:0;;58889:68;;;;-1:-1:-1;;;58889:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;59675:22:0;::::1;59667:73;;;;-1:-1:-1::0;;;59667:73:0::1;;;;;;;:::i;:::-;59751:28;59770:8;59751:18;:28::i;113483:296::-:0;113566:39;52062:4;113594:10;113566:7;:39::i;:::-;113558:69;;;;-1:-1:-1;;;113558:69:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;113648:33:0;;;;;;:13;:33;;;;;;;;113647:34;113639:79;;;;-1:-1:-1;;;113639:79:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;113730:33:0;;;;;:13;:33;;;;;:40;;-1:-1:-1;;113730:40:0;113766:4;113730:40;;;113483:296::o;101350:321::-;101441:39;52062:4;101469:10;101441:7;:39::i;:::-;101433:71;;;;-1:-1:-1;;;101433:71:0;;;;;;;:::i;:::-;101519:30;;-1:-1:-1;;;101519:30:0;;101552:6;;-1:-1:-1;;;;;101519:15:0;;;;;:30;;101543:4;;101519:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:39;101515:112;;;101585:30;;-1:-1:-1;;;101585:30:0;;-1:-1:-1;;;;;101585:15:0;;;;;:30;;101609:4;;101585:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101576:39;;101515:112;101637:26;;-1:-1:-1;;;101637:26:0;;-1:-1:-1;;;;;101637:14:0;;;;;:26;;101652:2;;101656:6;;101637:26;;;:::i;63007:98::-;63065:7;63092:5;63096:1;63092;:5;:::i;22373:157::-;22482:40;;;22497:25;22482:40;22373:157;;;:::o;36884:98::-;36964:10;36884:98;:::o;91349:381::-;-1:-1:-1;;;;;91486:19:0;;91478:68;;;;-1:-1:-1;;;91478:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;91565:21:0;;91557:68;;;;-1:-1:-1;;;91557:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;91638:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;;:36;;;91690:32;;;;;91668:6;;91690:32;:::i;:::-;;;;;;;;91349:381;;;:::o;86952:172::-;87004:6;86999:118;87020:11;;87016:1;:15;86999:118;;;87066:8;;;;:5;:8;;;;;;-1:-1:-1;;;;;87066:8:0;87053:37;87091:13;:11;:13::i;:::-;87053:52;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;87033:3:0;;;;:::i;:::-;;;;86999:118;;91854:1304;-1:-1:-1;;;;;91986:18:0;;91978:68;;;;-1:-1:-1;;;91978:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;92065:16:0;;92057:64;;;;-1:-1:-1;;;92057:64:0;;;;;;;:::i;:::-;92149:1;92140:6;:10;92132:64;;;;-1:-1:-1;;;92132:64:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;92216:17:0;;;;;;:13;:17;;;;;;;;92215:18;92207:27;;;;;;92245:38;92266:4;92272:2;92276:6;92245:20;:38::i;:::-;92299:25;92317:6;92299:17;:25::i;:::-;92296:54;;;92327:20;:18;:20::i;:::-;-1:-1:-1;;;;;92365:21:0;;;;;;:17;:21;;;;;;;;92362:155;;;-1:-1:-1;;;;;92428:12:0;;92405:20;92428:12;;;:6;:12;;;;;:19;:31;;92452:6;92428:23;:31::i;:::-;92405:54;;92475:29;92485:4;92491:12;92475:9;:29::i;:::-;92362:155;;-1:-1:-1;;;;;92531:23:0;;;;;;:17;:23;;;;;;;;92528:152;;;-1:-1:-1;;;;;92595:10:0;;92572:20;92595:10;;;:6;:10;;;;;:17;:29;;92617:6;92595:21;:29::i;:::-;92572:52;;92640:27;92650:2;92654:12;92640:9;:27::i;:::-;92528:152;;-1:-1:-1;;;;;92794:18:0;;92763:13;92794:18;;;:14;:18;;;;;;;;:52;;;;-1:-1:-1;92832:13:0;;-1:-1:-1;;;;;92816:30:0;;;92832:13;;92816:30;;92794:52;:80;;;;;92851:23;92869:4;92851:17;:23::i;:::-;92850:24;92794:80;92791:261;;;-1:-1:-1;92901:1:0;92791:261;;;-1:-1:-1;;;;;92923:21:0;;;;;;:15;:21;;;;;;;;92920:132;;;-1:-1:-1;92971:1:0;92920:132;;;-1:-1:-1;;;;;92993:19:0;;;;;;:15;:19;;;;;;;;92990:62;;;-1:-1:-1;93039:1:0;92990:62;93109:41;93124:4;93130:2;93134:6;93142:7;93109:14;:41::i;65286:240::-;65406:7;65467:12;65459:6;;;;65451:29;;;;-1:-1:-1;;;65451:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;65502:5:0;;;65286:240::o;63388:98::-;63446:7;63473:5;63477:1;63473;:5;:::i;53363:505::-;53452:22;53460:4;53466:7;53452;:22::i;:::-;53447:414;;53640:41;53668:7;-1:-1:-1;;;;;53640:41:0;53678:2;53640:19;:41::i;:::-;53754:38;53782:4;53789:2;53754:19;:38::i;:::-;53545:270;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;53545:270:0;;;;;;;;;;-1:-1:-1;;;53491:358:0;;;;;;;:::i;56999:238::-;57083:22;57091:4;57097:7;57083;:22::i;:::-;57078:152;;57122:12;;;;57154:4;57122:12;;;;;;;;-1:-1:-1;;;;;57122:29:0;;;;;;;;;;:36;;-1:-1:-1;;57122:36:0;;;;;;57205:12;:10;:12::i;:::-;-1:-1:-1;;;;;57178:40:0;57196:7;-1:-1:-1;;;;;57178:40:0;57190:4;57178:40;;;;;;;;;;56999:238;;:::o;57369:239::-;57453:22;57461:4;57467:7;57453;:22::i;:::-;57449:152;;;57524:5;57492:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;57492:29:0;;;;;;;;;:37;;-1:-1:-1;;57492:37:0;;;57576:12;:10;:12::i;:::-;-1:-1:-1;;;;;57549:40:0;57567:7;-1:-1:-1;;;;;57549:40:0;57561:4;57549:40;;;;;;;;;;57369:239;;:::o;116160:493::-;116249:4;116255:7;116296:1;116283:10;:14;116275:49;;;;-1:-1:-1;;;116275:49:0;;;;;;;:::i;:::-;116357:23;:21;:23::i;:::-;116343:10;:37;;116335:79;;;;-1:-1:-1;;;116335:79:0;;;;;;;:::i;:::-;116427:13;116443:40;:9;116472:10;116443:28;:40::i;:::-;116509:20;;116427:56;;-1:-1:-1;116500:29:0;;116496:150;;;116554:5;116561:1;116546:17;;;;;;;116496:150;116604:4;116610:9;:16;;116627:5;116610:23;;;;;;-1:-1:-1;;;116610:23:0;;;;;;;;;;;;;;;;;116596:38;;;;;116160:493;;;;;;:::o;117558:622::-;117701:44;117728:4;117734:2;117738:6;117701:26;:44::i;:::-;-1:-1:-1;;;;;117762:18:0;;117758:415;;117818:26;117841:2;117818:22;:26::i;:::-;117859:28;:26;:28::i;:::-;117758:415;;;-1:-1:-1;;;;;117909:16:0;;117905:268;;117963:28;117986:4;117963:22;:28::i;117905:268::-;118092:28;118115:4;118092:22;:28::i;:::-;118135:26;118158:2;118135:22;:26::i;102724:315::-;-1:-1:-1;;;;;102809:21:0;;102801:65;;;;-1:-1:-1;;;102801:65:0;;;;;;;:::i;:::-;102897:7;;:19;;102909:6;102897:11;:19::i;:::-;102887:7;:29;-1:-1:-1;;;;;102948:18:0;;;;;;:9;:18;;;;;;:30;;102971:6;102948:22;:30::i;:::-;-1:-1:-1;;;;;102927:18:0;;;;;;:9;:18;;;;;;:51;;;;102994:37;;102927:18;;;102994:37;;;;103024:6;;102994:37;:::i;:::-;;;;;;;;102724:315;;:::o;110033:947::-;110139:6;-1:-1:-1;;;;;110129:16:0;:6;-1:-1:-1;;;;;110129:16:0;;;:30;;;;;110158:1;110149:6;:10;110129:30;110125:848;;;-1:-1:-1;;;;;110180:20:0;;;110176:385;;-1:-1:-1;;;;;110288:22:0;;110269:16;110288:22;;;:14;:22;;;;;;;;;110349:13;:60;;110408:1;110349:60;;;-1:-1:-1;;;;;110365:19:0;;;;;;:11;:19;;;;;;110385:13;110397:1;110385:9;:13;:::i;:::-;110365:34;;;;;;;;;;;;;;;:40;;;110349:60;110329:80;-1:-1:-1;110428:17:0;110448:21;110329:80;110462:6;110448:13;:21::i;:::-;110428:41;;110488:57;110505:6;110513:9;110524;110535;110488:16;:57::i;:::-;110176:385;;;;-1:-1:-1;;;;;110581:20:0;;;110577:385;;-1:-1:-1;;;;;110689:22:0;;110670:16;110689:22;;;:14;:22;;;;;;;;;110750:13;:60;;110809:1;110750:60;;;-1:-1:-1;;;;;110766:19:0;;;;;;:11;:19;;;;;;110786:13;110798:1;110786:9;:13;:::i;:::-;110766:34;;;;;;;;;;;;;;;:40;;;110750:60;110730:80;-1:-1:-1;110829:17:0;110849:21;110730:80;110863:6;110849:13;:21::i;:::-;110829:41;;110889:57;110906:6;110914:9;110925;110936;110889:16;:57::i;103371:350::-;-1:-1:-1;;;;;103457:21:0;;103449:67;;;;-1:-1:-1;;;103449:67:0;;;;;;;:::i;:::-;103549:68;103572:6;103549:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;103549:18:0;;;;;;:9;:18;;;;;;;:68;:22;:68::i;:::-;-1:-1:-1;;;;;103528:18:0;;;;;;:9;:18;;;;;:89;103639:7;;:19;;103651:6;103639:11;:19::i;:::-;103629:7;:29;103675:37;;103701:1;;-1:-1:-1;;;;;103675:37:0;;;;;;;103705:6;;103675:37;:::i;109592:433::-;-1:-1:-1;;;;;109705:20:0;;;109679:23;109705:20;;;:9;:20;;;;;;;;;;109763;109715:9;109763;:20::i;:::-;-1:-1:-1;;;;;109840:20:0;;;;;;;:9;:20;;;;;;:32;;-1:-1:-1;;;;;;109840:32:0;;;;;;;;;;109890:54;;109736:47;;-1:-1:-1;109840:32:0;109890:54;;;;;;109840:20;109890:54;109957:60;109972:15;109989:9;110000:16;109957:14;:60::i;59947:191::-;60021:16;60040:6;;-1:-1:-1;;;;;60057:17:0;;;-1:-1:-1;;;;;;60057:17:0;;;;;;60090:40;;60040:6;;;;;;;60090:40;;60021:16;60090:40;59947:191;;:::o;101966:474::-;102115:24;102142:25;102152:5;102159:7;102142:9;:25::i;:::-;102115:52;;-1:-1:-1;;102183:16:0;:37;102179:253;;102266:6;102246:16;:26;;102238:68;;;;-1:-1:-1;;;102238:68:0;;;;;;;:::i;:::-;102352:51;102361:5;102368:7;102396:6;102377:16;:25;102352:8;:51::i;99886:258::-;99949:7;99969:13;99985:11;;99999:1;99985:15;;;;:::i;:::-;99969:31;;100015:9;100011:101;100034:11;;100030:1;:15;100011:101;;;100070:9;;;;:6;:9;;;;;;-1:-1:-1;;;;;100070:19:0;;;:9;;:19;100067:33;;;100099:1;100091:9;;100067:33;100047:3;;;;:::i;:::-;;;;100011:101;;;-1:-1:-1;100131:5:0;99886:258;-1:-1:-1;;99886:258:0:o;97362:439::-;97457:16;;;97471:1;97457:16;;;;;;;;97433:21;;97457:16;;;;;;;;;;-1:-1:-1;97457:16:0;97433:40;;97494:5;97484:4;97489:1;97484:7;;;;;;-1:-1:-1;;;97484:7:0;;;;;;;;;-1:-1:-1;;;;;97484:15:0;;;:7;;;;;;;;;:15;97520:4;;97510:7;;97520:4;;;97510;;97520;;97510:7;;;;-1:-1:-1;;;97510:7:0;;;;;;;;;-1:-1:-1;;;;;97510:14:0;;;:7;;;;;;;;;:14;97567:13;;97537:53;;-1:-1:-1;;;97537:53:0;;:21;;;;;;:53;;97567:13;;;97583:6;;97537:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;97601:13:0;;:192;;-1:-1:-1;;;97601:192:0;;-1:-1:-1;;;;;97601:13:0;;;;:67;;:192;;97683:6;;97601:13;;97720:4;;97747;;97767:15;;97601:192;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97362:439;;;:::o;63745:98::-;63803:7;63830:5;63834:1;63830;:5;:::i;64144:98::-;64202:7;64229:5;64233:1;64229;:5;:::i;115292:127::-;115356:7;115383:28;:18;:26;:28::i;115061:223::-;115108:7;115128:30;:18;:28;:30::i;:::-;115171:17;115191:23;:21;:23::i;:::-;115171:43;;115230:19;115239:9;115230:19;;;;;;:::i;:::-;;;;;;;;115267:9;-1:-1:-1;115061:223:0;:::o;100799:248::-;100867:4;;;100914:100;100934:11;;100930:1;:15;100914:100;;;100970:8;;;;:5;:8;;;;;;-1:-1:-1;;;;;100970:17:0;;;:8;;:17;100967:35;;;100998:4;100989:13;;100967:35;100947:3;;;;:::i;:::-;;;;100914:100;;111867:153;111977:9;111867:153;:::o;97865:455::-;97969:11;;97931:4;;-1:-1:-1;;;;;97969:11:0;97955:10;:25;;;;:45;;-1:-1:-1;97994:6:0;;-1:-1:-1;;;97994:6:0;;;;97993:7;97955:45;:85;;;;-1:-1:-1;98013:8:0;:27;;;97955:85;:177;;;;-1:-1:-1;98085:31:0;;98053:29;;98120:12;;98053:63;;;:::i;:::-;:79;;97955:177;:302;;;;-1:-1:-1;98231:26:0;;98196:4;;98181:46;;-1:-1:-1;;;98181:46:0;;-1:-1:-1;;;;;98196:4:0;;;;98181:31;;:46;;98221:4;;98181:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:76;;97955:302;:357;;;;-1:-1:-1;;98280:32:0;;-1:-1:-1;98270:42:0;;97865:455::o;98358:383::-;98418:26;;98408:51;;80395:42;98408:9;:51::i;:::-;98502:12;98470:29;:44;98595:26;;98559:31;;:63;;:35;:63::i;:::-;98525:31;:97;;;98670:23;;-1:-1:-1;98633:101:0;;;98696:8;:35;;-1:-1:-1;;98696:35:0;;;98358:383::o;112260:387::-;112345:1;112336:6;:10;:40;;;;-1:-1:-1;;;;;;112350:14:0;;;;;;:6;:14;;;;;:21;:26;112336:40;112333:188;;;112393:17;112403:6;112393:9;:17::i;:::-;112333:188;;;112431:11;;:40;;;;-1:-1:-1;;;;;;112446:14:0;;112470:1;112446:14;;;:6;:14;;;;;:21;:25;;112431:40;112428:93;;;112488:20;112501:6;112488:12;:20::i;:::-;-1:-1:-1;;;;;112562:14:0;;;;;;:6;:14;;;;;:21;112546:11;;:50;;112589:6;;112546:38;;:15;:38::i;:50::-;112532:11;:64;-1:-1:-1;;;;;112608:14:0;;;;;;;:6;:14;;;;;:30;112260:387::o;93595:1608::-;93707:12;;;93704:257;;93736:14;:12;:14::i;:::-;93704:257;;;93771:7;:12;;93782:1;93771:12;93768:193;;;93800:12;:10;:12::i;93768:193::-;93833:7;:12;;93844:1;93833:12;93830:131;;;93862:18;:16;:18::i;93830:131::-;93901:7;:12;;93912:1;93901:12;93898:63;;;93930:19;:17;:19::i;:::-;93973:24;94000:18;94011:6;94000:10;:18::i;:::-;93973:45;;94049:53;94071:6;94049:53;;;;;;;;;;;;;;;;;:9;:17;94059:6;-1:-1:-1;;;;;94049:17:0;-1:-1:-1;;;;;94049:17:0;;;;;;;;;;;;;:21;;:53;;;;;:::i;:::-;-1:-1:-1;;;;;94029:17:0;;;;;;;:9;:17;;;;;;:73;;;;94161:22;;94136:20;;;;;;;;;;:48;;:24;:48::i;:::-;-1:-1:-1;;;;;94113:20:0;;;;;;:9;:20;;;;;:71;94195:18;94205:7;94195:9;:18::i;:::-;94248:9;-1:-1:-1;;;;;94231:51:0;94240:6;-1:-1:-1;;;;;94231:51:0;;94259:7;:22;;;94231:51;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;94298:17:0;;;94327:1;94298:17;;;:9;:17;;;;;;;94295:89;;-1:-1:-1;;;;;94346:17:0;;;;;;:9;:17;;;;;:26;;-1:-1:-1;;;;;;94346:26:0;;;;;;94295:89;-1:-1:-1;;;;;94399:20:0;;;94431:1;94399:20;;;:9;:20;;;;;;;94396:98;;-1:-1:-1;;;;;94450:20:0;;;;;;:9;:20;;;;;:32;;-1:-1:-1;;;;;;94450:32:0;;;;;;94396:98;94519:22;;94509:32;;94506:432;;;-1:-1:-1;;;;;94574:17:0;;;;;;;:9;:17;;;;;;;94593:20;;;;;;;;94559:63;;94574:17;;;;94593:20;94615:6;94559:14;:63::i;:::-;94506:432;;;-1:-1:-1;;;;;94672:17:0;;;;;;;:9;:17;;;;;;;94691:20;;;;;;;;94713:22;;94657:79;;94672:17;;;;94691:20;;;;;94657:14;:79::i;:::-;-1:-1:-1;;;;;94767:17:0;;;;;;;:9;:17;;;;;;;;;94796:31;;;;94786:42;;;;;94830:19;;;;94752:98;;94767:17;;;;94786:42;;;;;94752:14;:98::i;:::-;-1:-1:-1;;;;;94881:17:0;;;;;;;:9;:17;;;;;;94912:12;;;;94866:59;;94881:17;;;;;;94866:14;:59::i;:::-;94953:12;;;;;:28;;;94969:7;:12;;94980:1;94969:12;94953:28;94950:246;;;94998:15;:13;:15::i;:::-;94950:246;;;95034:7;:12;;95045:1;95034:12;:28;;;;95050:7;:12;;95061:1;95050:12;95034:28;95031:165;;;95079:15;:13;:15::i;:::-;95131:31;;95164:19;;;;95114:70;;-1:-1:-1;;;;;95131:31:0;;;;95114:70;;;;;;;95164:19;95114:70;:::i;:::-;;;;;;;;93595:1608;;;;;:::o;24203:451::-;24278:13;24304:19;24336:10;24340:6;24336:1;:10;:::i;:::-;:14;;24349:1;24336:14;:::i;:::-;24326:25;;;;;;-1:-1:-1;;;24326:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24326:25:0;;24304:47;;24362:15;:6;24369:1;24362:9;;;;;;-1:-1:-1;;;24362:9:0;;;;;;;;;;;;:15;-1:-1:-1;;;;;24362:15:0;;;;;;;;;24388;:6;24395:1;24388:9;;;;;;-1:-1:-1;;;24388:9:0;;;;;;;;;;;;:15;-1:-1:-1;;;;;24388:15:0;;;;;;;;-1:-1:-1;24419:9:0;24431:10;24435:6;24431:1;:10;:::i;:::-;:14;;24444:1;24431:14;:::i;:::-;24419:26;;24414:135;24451:1;24447;:5;24414:135;;;24486:12;24499:5;24507:3;24499:11;24486:25;;;;;-1:-1:-1;;;24486:25:0;;;;;;;;;;;;24474:6;24481:1;24474:9;;;;;;-1:-1:-1;;;24474:9:0;;;;;;;;;;;;:37;-1:-1:-1;;;;;24474:37:0;;;;;;;;-1:-1:-1;24536:1:0;24526:11;;;;;24454:3;;;:::i;:::-;;;24414:135;;;-1:-1:-1;24567:10:0;;24559:55;;;;-1:-1:-1;;;24559:55:0;;;;;;;:::i;16052:918::-;16165:12;;16141:7;;16161:58;;-1:-1:-1;16206:1:0;16199:8;;16161:58;16272:12;;16231:11;;16297:424;16310:4;16304:3;:10;16297:424;;;16331:11;16345:23;16358:3;16363:4;16345:12;:23::i;:::-;16331:37;;16602:7;16589:5;16595:3;16589:10;;;;;;-1:-1:-1;;;16589:10:0;;;;;;;;;;;;;;;;;:20;16585:125;;;16637:3;16630:10;;16585:125;;;16687:7;:3;16693:1;16687:7;:::i;:::-;16681:13;;16585:125;16297:424;;;;16847:1;16841:3;:7;:36;;;;-1:-1:-1;16870:7:0;16852:5;16858:7;16864:1;16858:3;:7;:::i;:::-;16852:14;;;;;;-1:-1:-1;;;16852:14:0;;;;;;;;;;;;;;;;;:25;16841:36;16837:126;;;16901:7;16907:1;16901:3;:7;:::i;:::-;16894:14;;;;;;16837:126;-1:-1:-1;16948:3:0;-1:-1:-1;16941:10:0;;116710:176;-1:-1:-1;;;;;116794:33:0;;;;;;:24;:33;;;;;;;;116853:6;:15;;;;;;:22;116778:100;;116794:33;116830:46;;:18;116819:7;116830:9;:18::i;:46::-;116778:15;:100::i;116894:118::-;116951:53;116967:21;116990:13;:11;:13::i;110988:702::-;111163:18;111184:78;111191:12;111184:78;;;;;;;;;;;;;;;;;:6;:78::i;:::-;111163:99;;111294:1;111279:12;:16;;;:85;;;;-1:-1:-1;;;;;;111299:22:0;;;;;;:11;:22;;;;;:65;;;;111322:16;111337:1;111322:12;:16;:::i;:::-;111299:40;;;;;;;;;;;;;;;-1:-1:-1;111299:40:0;:50;;:65;111279:85;111275:339;;;-1:-1:-1;;;;;111381:22:0;;;;;;:11;:22;;;;;111430:8;;111404:16;111419:1;111404:12;:16;:::i;:::-;111381:40;;;;;;;;;;;;;-1:-1:-1;111381:40:0;:46;;:57;111275:339;;;111510:33;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;111471:22:0;;-1:-1:-1;111471:22:0;;;:11;:22;;;;;:36;;;;;;;;;;;:72;;;;-1:-1:-1;;111471:72:0;;;;;;;;-1:-1:-1;111471:72:0;;;;111586:16;;111471:36;;111586:16;:::i;:::-;-1:-1:-1;;;;;111558:25:0;;;;;;:14;:25;;;;;:44;;-1:-1:-1;;111558:44:0;;;;;;;;;;;;111275:339;111652:9;-1:-1:-1;;;;;111631:51:0;;111663:8;111673;111631:51;;;;;;;:::i;:::-;;;;;;;;110988:702;;;;;:::o;13513:114::-;13605:14;;13513:114::o;13635:127::-;13724:19;;13742:1;13724:19;;;13635:127::o;98792:440::-;80525:6;:13;;-1:-1:-1;;;;80525:13:0;-1:-1:-1;;;80525:13:0;;;98892:16:::1;::::0;;98906:1:::1;98892:16:::0;;;;;::::1;::::0;;-1:-1:-1;;98892:16:0::1;::::0;::::1;::::0;;::::1;::::0;::::1;-1:-1:-1::0;;98929:4:0::1;::::0;98919:7;;;;-1:-1:-1;;;;;;98929:4:0::1;::::0;98919:7;;-1:-1:-1;98929:4:0::1;::::0;98919:7:::1;;-1:-1:-1::0;;;98919:7:0::1;;;;;;;;;;;;;;:14;-1:-1:-1::0;;;;;98919:14:0::1;;;-1:-1:-1::0;;;;;98919:14:0::1;;;::::0;::::1;98962:4;98944;98949:1;98944:7;;;;;;-1:-1:-1::0;;;98944:7:0::1;;;;;;;;;-1:-1:-1::0;;;;;98944:23:0;;::::1;:7;::::0;;::::1;::::0;;;;;:23;98987:4:::1;::::0;99009:13:::1;::::0;98980:52:::1;::::0;-1:-1:-1;;;98980:52:0;;98987:4;;::::1;::::0;98980:20:::1;::::0;:52:::1;::::0;99009:13;;::::1;::::0;99025:6;;98980:52:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;99043:13:0::1;::::0;:181:::1;::::0;-1:-1:-1;;;99043:181:0;;-1:-1:-1;;;;;99043:13:0;;::::1;::::0;:67:::1;::::0;:181:::1;::::0;99125:6;;99043:13:::1;::::0;99162:4;;99181:2;;99198:15:::1;::::0;99043:181:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;80543:6:0;:14;;-1:-1:-1;;;;80543:14:0;;;-1:-1:-1;;;;;98792:440:0:o;112654:135::-;112734:7;:14;;-1:-1:-1;;;;;112710:21:0;;;;;;;:13;:21;;;;;:38;;;112760:20;;;;;;;;;;;;;;;-1:-1:-1;;;;;;112760:20:0;;;;;;112654:135::o;112796:227::-;112888:7;112896:14;;:16;;112911:1;;112896:16;:::i;:::-;112888:25;;;;;;-1:-1:-1;;;112888:25:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;112863:21:0;;;;;:13;:21;;;;;;;;112855:7;:30;;112888:25;;;;;112855:7;:30;;;;-1:-1:-1;;;112855:30:0;;;;;;;;;;;;;;;;;;;;;:58;;-1:-1:-1;;;;;;112855:58:0;-1:-1:-1;;;;;112855:58:0;;;;;;112968:21;;;;;:13;:21;;;;;;;;112939:7;112947:14;;112968:21;;:13;112855:30;112947:16;;-1:-1:-1;;112947:16:0;:::i;:::-;112939:25;;;;;;-1:-1:-1;;;112939:25:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;112939:25:0;112925:40;;;;;;;;;;;;:64;113001:7;:13;;;;;-1:-1:-1;;;113001:13:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;113001:13:0;;;;;-1:-1:-1;;;;;;113001:13:0;;;;;;-1:-1:-1;112796:227:0:o;90621:115::-;90680:12;90664:28;;:13;:28;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;90664:28:0;;;-1:-1:-1;;;;;;90664:28:0;;;;;;;90718:10;90703:25;;;;;;;;;;;;;;;;;;;;;;;;;;;90621:115::o;90744:112::-;90801:12;90785:28;;:13;:28;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;90785:28:0;;;-1:-1:-1;;;;;;90785:28:0;;;;;;;90839:9;90824:24;;;;;;;;;;;;;;;;;;;;;;;;;;;90744:112::o;90864:124::-;90927:12;90911:28;;:13;:28;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;90911:28:0;;;-1:-1:-1;;;;;;90911:28:0;;;;;;;90965:15;90950:30;;;;;;;;;;;;;;;;;;;;;;;;;;;90864:124::o;90996:126::-;91060:12;91044:28;;:13;:28;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;91044:28:0;;;-1:-1:-1;;;;;;91044:28:0;;;;;;;91098:16;91083:31;;;;;;;;;;;;;;;;;;;;;;;;;;;90996:126::o;89939:471::-;89998:16;;:::i;:::-;90027:23;90053:220;;;;;;;;90077:1;90053:220;;;;90093:50;90106:7;90115:12;:27;;;90093:12;:50::i;:::-;90053:220;;;;90158:46;90171:7;90180:12;:23;;;90158:12;:46::i;:::-;90053:220;;;;90219:43;90232:7;90241:12;:20;;;90219:12;:43::i;:::-;90053:220;;;90027:246;;90310:68;90366:6;:11;;;90310:51;90346:6;:14;;;90310:31;90322:6;:18;;;90310:7;:11;;:31;;;;:::i;:68::-;90286:92;;;89939:471;-1:-1:-1;;89939:471:0:o;95211:168::-;95283:18;;;;95303:31;;95274:61;;95283:18;-1:-1:-1;;;;;95303:31:0;95274:8;:61::i;:::-;95346:25;95359:6;:11;;;95346:12;:25::i;91130:80::-;91189:13;91174:28;:12;:28;;;;;;;;;;;;;;-1:-1:-1;;;;;;91174:28:0;-1:-1:-1;;;;;91174:28:0;;;;;;;;;91130:80::o;14836:156::-;14898:7;14973:11;14983:1;14974:5;;;14973:11;:::i;:::-;14963:21;;14964:5;;;14963:21;:::i;117020:310::-;117115:17;117135:23;:21;:23::i;:::-;117115:43;-1:-1:-1;117115:43:0;117173:30;117189:9;117173:15;:30::i;:::-;:42;117169:154;;;117232:29;;;;;;;;-1:-1:-1;117232:29:0;;;;;;;;;;;;;;117276:16;;;:35;;;;;;;;;;;;;;;117020:310::o;111698:161::-;111773:6;111811:12;111804:5;111800:9;;111792:32;;;;-1:-1:-1;;;111792:32:0;;;;;;;;:::i;:::-;-1:-1:-1;111849:1:0;;111698:161;-1:-1:-1;;111698:161:0:o;90418:195::-;90493:7;90516:9;90513:22;;-1:-1:-1;90534:1:0;90527:8;;90513:22;90553:52;90589:5;90553:17;:7;90565:4;90553:11;:17::i;95387:218::-;-1:-1:-1;;;;;95463:23:0;;95460:35;;95488:7;;95460:35;95508:12;95505:24;;95522:7;;95505:24;-1:-1:-1;;;;;95564:20:0;;;;;;:9;:20;;;;;;:33;;95589:7;95564:24;:33::i;:::-;-1:-1:-1;;;;;95541:20:0;;;;;;:9;:20;;;;;:56;95387:218;;:::o;95613:202::-;95673:11;95670:23;;95686:7;;95670:23;95750:4;95732:24;;;;:9;:24;;;;;;:36;;95761:6;95732:28;:36::i;:::-;95723:4;95705:24;;;;:9;:24;;;;;:63;;;;95779:28;;95800:6;95779:5;:28::i;117338:212::-;117432:10;;117408:7;;117428:115;;-1:-1:-1;117471:1:0;117464:8;;117428:115;117516:10;;117512:3;;117516:14;;117529:1;;117516:14;:::i;:::-;117512:19;;;;;;-1:-1:-1;;;117512:19:0;;;;;;;;;;;;;;;;;117505:26;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:259:1:-;;126:2;114:9;105:7;101:23;97:32;94:2;;;147:6;139;132:22;94:2;191:9;178:23;210:33;237:5;210:33;:::i;278:263::-;;401:2;389:9;380:7;376:23;372:32;369:2;;;422:6;414;407:22;369:2;459:9;453:16;478:33;505:5;478:33;:::i;546:402::-;;;675:2;663:9;654:7;650:23;646:32;643:2;;;696:6;688;681:22;643:2;740:9;727:23;759:33;786:5;759:33;:::i;:::-;811:5;-1:-1:-1;868:2:1;853:18;;840:32;881:35;840:32;881:35;:::i;:::-;935:7;925:17;;;633:315;;;;;:::o;953:470::-;;;;1099:2;1087:9;1078:7;1074:23;1070:32;1067:2;;;1120:6;1112;1105:22;1067:2;1164:9;1151:23;1183:33;1210:5;1183:33;:::i;:::-;1235:5;-1:-1:-1;1292:2:1;1277:18;;1264:32;1305:35;1264:32;1305:35;:::i;:::-;1057:366;;1359:7;;-1:-1:-1;;;1413:2:1;1398:18;;;;1385:32;;1057:366::o;1428:396::-;;;1554:2;1542:9;1533:7;1529:23;1525:32;1522:2;;;1575:6;1567;1560:22;1522:2;1619:9;1606:23;1638:33;1665:5;1638:33;:::i;:::-;1690:5;-1:-1:-1;1747:2:1;1732:18;;1719:32;1760;1719;1760;:::i;1829:327::-;;;1958:2;1946:9;1937:7;1933:23;1929:32;1926:2;;;1979:6;1971;1964:22;1926:2;2023:9;2010:23;2042:33;2069:5;2042:33;:::i;:::-;2094:5;2146:2;2131:18;;;;2118:32;;-1:-1:-1;;;1916:240:1:o;2161:709::-;;;;;;;2356:3;2344:9;2335:7;2331:23;2327:33;2324:2;;;2378:6;2370;2363:22;2324:2;2422:9;2409:23;2441:33;2468:5;2441:33;:::i;:::-;2493:5;-1:-1:-1;2545:2:1;2530:18;;2517:32;;-1:-1:-1;2596:2:1;2581:18;;2568:32;;-1:-1:-1;2652:2:1;2637:18;;2624:32;2700:4;2687:18;;2675:31;;2665:2;;2725:6;2717;2710:22;2665:2;2314:556;;;;-1:-1:-1;2314:556:1;;2807:3;2792:19;;2779:33;;2859:3;2844:19;;;2831:33;;-1:-1:-1;2314:556:1;-1:-1:-1;;2314:556:1:o;2875:441::-;;;3003:2;2991:9;2982:7;2978:23;2974:32;2971:2;;;3024:6;3016;3009:22;2971:2;3068:9;3055:23;3087:33;3114:5;3087:33;:::i;:::-;3139:5;-1:-1:-1;3196:2:1;3181:18;;3168:32;3244:10;3231:24;;3219:37;;3209:2;;3275:6;3267;3260:22;3321:257;;3441:2;3429:9;3420:7;3416:23;3412:32;3409:2;;;3462:6;3454;3447:22;3409:2;3499:9;3493:16;3518:30;3542:5;3518:30;:::i;3583:527::-;;;;;;3760:3;3748:9;3739:7;3735:23;3731:33;3728:2;;;3782:6;3774;3767:22;3728:2;3826:9;3813:23;3845:30;3869:5;3845:30;:::i;:::-;3894:5;3946:2;3931:18;;3918:32;;-1:-1:-1;3997:2:1;3982:18;;3969:32;;4048:2;4033:18;;4020:32;;-1:-1:-1;4099:3:1;4084:19;4071:33;;-1:-1:-1;3718:392:1;-1:-1:-1;;;3718:392:1:o;4115:190::-;;4227:2;4215:9;4206:7;4202:23;4198:32;4195:2;;;4248:6;4240;4233:22;4195:2;-1:-1:-1;4276:23:1;;4185:120;-1:-1:-1;4185:120:1:o;4310:327::-;;;4439:2;4427:9;4418:7;4414:23;4410:32;4407:2;;;4460:6;4452;4445:22;4407:2;4501:9;4488:23;4478:33;;4561:2;4550:9;4546:18;4533:32;4574:33;4601:5;4574:33;:::i;4642:352::-;;4753:2;4741:9;4732:7;4728:23;4724:32;4721:2;;;4774:6;4766;4759:22;4721:2;4818:9;4805:23;4868:66;4861:5;4857:78;4850:5;4847:89;4837:2;;4955:6;4947;4940:22;4999:485;;;;5160:2;5148:9;5139:7;5135:23;5131:32;5128:2;;;5181:6;5173;5166:22;5128:2;5225:9;5212:23;5244:33;5271:5;5244:33;:::i;:::-;5296:5;-1:-1:-1;5348:2:1;5333:18;;5320:32;;-1:-1:-1;5404:2:1;5389:18;;5376:32;5417:35;5376:32;5417:35;:::i;:::-;5471:7;5461:17;;;5118:366;;;;;:::o;5684:194::-;;5807:2;5795:9;5786:7;5782:23;5778:32;5775:2;;;5828:6;5820;5813:22;5775:2;-1:-1:-1;5856:16:1;;5765:113;-1:-1:-1;5765:113:1:o;5883:327::-;;;6012:2;6000:9;5991:7;5987:23;5983:32;5980:2;;;6033:6;6025;6018:22;6215:444;6485:66;6473:79;;6577:1;6568:11;;6561:27;;;;6613:2;6604:12;;6597:28;6650:2;6641:12;;6463:196::o;6664:786::-;;7075:25;7070:3;7063:38;7130:6;7124:13;7146:62;7201:6;7196:2;7191:3;7187:12;7180:4;7172:6;7168:17;7146:62;:::i;:::-;7272:19;7267:2;7227:16;;;7259:11;;;7252:40;7317:13;;7339:63;7317:13;7388:2;7380:11;;7373:4;7361:17;;7339:63;:::i;:::-;7422:17;7441:2;7418:26;;7053:397;-1:-1:-1;;;;7053:397:1:o;7455:226::-;-1:-1:-1;;;;;7619:55:1;;;;7601:74;;7589:2;7574:18;;7556:125::o;7686:327::-;-1:-1:-1;;;;;7939:15:1;;;7921:34;;7991:15;;7986:2;7971:18;;7964:43;7848:2;7833:18;;7815:198::o;8018:398::-;-1:-1:-1;;;;;8299:15:1;;;8281:34;;8351:15;;;;8346:2;8331:18;;8324:43;8398:2;8383:18;;8376:34;;;;8208:2;8193:18;;8175:241::o;8421:297::-;-1:-1:-1;;;;;8613:55:1;;;;8595:74;;8700:2;8685:18;;8678:34;8583:2;8568:18;;8550:168::o;8723:187::-;8888:14;;8881:22;8863:41;;8851:2;8836:18;;8818:92::o;8915:617::-;9249:14;;9242:22;9224:41;;9296:2;9281:18;;9274:34;;;;9339:2;9324:18;;9317:34;;;;9382:2;9367:18;;9360:34;;;;9425:3;9410:19;;9403:35;9469:3;9454:19;;9447:35;9513:3;9498:19;;9491:35;9211:3;9196:19;;9178:354::o;9537:177::-;9683:25;;;9671:2;9656:18;;9638:76::o;9719:440::-;9950:25;;;-1:-1:-1;;;;;10011:55:1;;;;10006:2;9991:18;;9984:83;10098:2;10083:18;;10076:34;10141:2;10126:18;;10119:34;9937:3;9922:19;;9904:255::o;10164:440::-;10395:25;;;10451:2;10436:18;;10429:34;;;;10494:2;10479:18;;10472:34;-1:-1:-1;;;;;10542:55:1;10537:2;10522:18;;10515:83;10382:3;10367:19;;10349:255::o;10609:398::-;10836:25;;;10909:4;10897:17;;;;10892:2;10877:18;;10870:45;10946:2;10931:18;;10924:34;10989:2;10974:18;;10967:34;10823:3;10808:19;;10790:217::o;11265:383::-;;11414:2;11403:9;11396:21;11446:6;11440:13;11489:6;11484:2;11473:9;11469:18;11462:34;11505:66;11564:6;11559:2;11548:9;11544:18;11539:2;11531:6;11527:15;11505:66;:::i;:::-;11632:2;11611:15;-1:-1:-1;;11607:29:1;11592:45;;;;11639:2;11588:54;;11386:262;-1:-1:-1;;11386:262:1:o;11653:353::-;11855:2;11837:21;;;11894:2;11874:18;;;11867:30;11933:31;11928:2;11913:18;;11906:59;11997:2;11982:18;;11827:179::o;12011:356::-;12213:2;12195:21;;;12232:18;;;12225:30;12291:34;12286:2;12271:18;;12264:62;12358:2;12343:18;;12185:182::o;12372:356::-;12574:2;12556:21;;;12593:18;;;12586:30;12652:34;12647:2;12632:18;;12625:62;12719:2;12704:18;;12546:182::o;12733:341::-;12935:2;12917:21;;;12974:2;12954:18;;;12947:30;13013:19;13008:2;12993:18;;12986:47;13065:2;13050:18;;12907:167::o;13079:355::-;13281:2;13263:21;;;13320:2;13300:18;;;13293:30;13359:33;13354:2;13339:18;;13332:61;13425:2;13410:18;;13253:181::o;13439:401::-;13641:2;13623:21;;;13680:2;13660:18;;;13653:30;13719:34;13714:2;13699:18;;13692:62;13790:7;13785:2;13770:18;;13763:35;13830:3;13815:19;;13613:227::o;13845:400::-;14047:2;14029:21;;;14086:2;14066:18;;;14059:30;14125:34;14120:2;14105:18;;14098:62;14196:6;14191:2;14176:18;;14169:34;14235:3;14220:19;;14019:226::o;14250:343::-;14452:2;14434:21;;;14491:2;14471:18;;;14464:30;14530:21;14525:2;14510:18;;14503:49;14584:2;14569:18;;14424:169::o;14598:402::-;14800:2;14782:21;;;14839:2;14819:18;;;14812:30;14878:34;14873:2;14858:18;;14851:62;14949:8;14944:2;14929:18;;14922:36;14990:3;14975:19;;14772:228::o;15005:353::-;15207:2;15189:21;;;15246:2;15226:18;;;15219:30;15285:31;15280:2;15265:18;;15258:59;15349:2;15334:18;;15179:179::o;15363:480::-;15565:2;15547:21;;;15604:2;15584:18;;;15577:30;15643:34;15638:2;15623:18;;15616:62;15714:34;15709:2;15694:18;;15687:62;15786:14;15780:3;15765:19;;15758:43;15833:3;15818:19;;15537:306::o;15848:340::-;16050:2;16032:21;;;16089:2;16069:18;;;16062:30;16128:18;16123:2;16108:18;;16101:46;16179:2;16164:18;;16022:166::o;16193:350::-;16395:2;16377:21;;;16434:2;16414:18;;;16407:30;16473:28;16468:2;16453:18;;16446:56;16534:2;16519:18;;16367:176::o;16548:346::-;16750:2;16732:21;;;16789:2;16769:18;;;16762:30;16828:24;16823:2;16808:18;;16801:52;16885:2;16870:18;;16722:172::o;16899:355::-;17101:2;17083:21;;;17140:2;17120:18;;;17113:30;17179:33;17174:2;17159:18;;17152:61;17245:2;17230:18;;17073:181::o;17259:356::-;17461:2;17443:21;;;17480:18;;;17473:30;17539:34;17534:2;17519:18;;17512:62;17606:2;17591:18;;17433:182::o;17620:405::-;17822:2;17804:21;;;17861:2;17841:18;;;17834:30;17900:34;17895:2;17880:18;;17873:62;17971:11;17966:2;17951:18;;17944:39;18015:3;18000:19;;17794:231::o;18030:399::-;18232:2;18214:21;;;18271:2;18251:18;;;18244:30;18310:34;18305:2;18290:18;;18283:62;18381:5;18376:2;18361:18;;18354:33;18419:3;18404:19;;18204:225::o;18434:397::-;18636:2;18618:21;;;18675:2;18655:18;;;18648:30;18714:34;18709:2;18694:18;;18687:62;18785:3;18780:2;18765:18;;18758:31;18821:3;18806:19;;18608:223::o;18836:400::-;19038:2;19020:21;;;19077:2;19057:18;;;19050:30;19116:34;19111:2;19096:18;;19089:62;19187:6;19182:2;19167:18;;19160:34;19226:3;19211:19;;19010:226::o;19241:346::-;19443:2;19425:21;;;19482:2;19462:18;;;19455:30;19521:24;19516:2;19501:18;;19494:52;19578:2;19563:18;;19415:172::o;19592:404::-;19794:2;19776:21;;;19833:2;19813:18;;;19806:30;19872:34;19867:2;19852:18;;19845:62;19943:10;19938:2;19923:18;;19916:38;19986:3;19971:19;;19766:230::o;20001:398::-;20203:2;20185:21;;;20242:2;20222:18;;;20215:30;20281:34;20276:2;20261:18;;20254:62;20352:4;20347:2;20332:18;;20325:32;20389:3;20374:19;;20175:224::o;20404:405::-;20606:2;20588:21;;;20645:2;20625:18;;;20618:30;20684:34;20679:2;20664:18;;20657:62;20755:11;20750:2;20735:18;;20728:39;20799:3;20784:19;;20578:231::o;20814:342::-;21016:2;20998:21;;;21055:2;21035:18;;;21028:30;21094:20;21089:2;21074:18;;21067:48;21147:2;21132:18;;20988:168::o;21161:404::-;21363:2;21345:21;;;21402:2;21382:18;;;21375:30;21441:34;21436:2;21421:18;;21414:62;21512:10;21507:2;21492:18;;21485:38;21555:3;21540:19;;21335:230::o;21570:411::-;21772:2;21754:21;;;21811:2;21791:18;;;21784:30;21850:34;21845:2;21830:18;;21823:62;21921:17;21916:2;21901:18;;21894:45;21971:3;21956:19;;21744:237::o;22168:1029::-;;22478:3;22467:9;22463:19;22509:6;22498:9;22491:25;22535:2;22573:6;22568:2;22557:9;22553:18;22546:34;22616:3;22611:2;22600:9;22596:18;22589:31;22640:6;22675;22669:13;22706:6;22698;22691:22;22744:3;22733:9;22729:19;22722:26;;22783:2;22775:6;22771:15;22757:29;;22804:4;22817:218;22831:6;22828:1;22825:13;22817:218;;;22896:13;;-1:-1:-1;;;;;22892:62:1;22880:75;;23010:15;;;;22975:12;;;;22853:1;22846:9;22817:218;;;-1:-1:-1;;;;;;;23091:55:1;;;;23086:2;23071:18;;23064:83;-1:-1:-1;;;23178:3:1;23163:19;23156:35;23052:3;22439:758;-1:-1:-1;;;22439:758:1:o;23202:248::-;23376:25;;;23432:2;23417:18;;23410:34;23364:2;23349:18;;23331:119::o;23900:192::-;24074:10;24062:23;;;;24044:42;;24032:2;24017:18;;23999:93::o;24097:263::-;24299:10;24287:23;;;;24269:42;;24342:2;24327:18;;24320:34;24257:2;24242:18;;24224:136::o;24365:184::-;24537:4;24525:17;;;;24507:36;;24495:2;24480:18;;24462:87::o;24554:128::-;;24625:1;24621:6;24618:1;24615:13;24612:2;;;24631:18;;:::i;:::-;-1:-1:-1;24667:9:1;;24602:80::o;24687:228::-;;24754:10;24791:2;24788:1;24784:10;24821:2;24818:1;24814:10;24852:3;24848:2;24844:12;24839:3;24836:21;24833:2;;;24860:18;;:::i;:::-;24896:13;;24734:181;-1:-1:-1;;;;24734:181:1:o;24920:120::-;;24986:1;24976:2;;24991:18;;:::i;:::-;-1:-1:-1;25025:9:1;;24966:74::o;25045:191::-;;25110:10;25147:2;25144:1;25140:10;25169:3;25159:2;;25176:18;;:::i;:::-;25214:10;;25210:20;;;;;25090:146;-1:-1:-1;;25090:146:1:o;25241:168::-;;25347:1;25343;25339:6;25335:14;25332:1;25329:21;25324:1;25317:9;25310:17;25306:45;25303:2;;;25354:18;;:::i;:::-;-1:-1:-1;25394:9:1;;25293:116::o;25414:125::-;;25482:1;25479;25476:8;25473:2;;;25487:18;;:::i;:::-;-1:-1:-1;25524:9:1;;25463:76::o;25544:221::-;;25612:10;25672;;;;25642;;25694:12;;;25691:2;;;25709:18;;:::i;:::-;25746:13;;25592:173;-1:-1:-1;;;25592:173:1:o;25770:258::-;25842:1;25852:113;25866:6;25863:1;25860:13;25852:113;;;25942:11;;;25936:18;25923:11;;;25916:39;25888:2;25881:10;25852:113;;;25983:6;25980:1;25977:13;25974:2;;;-1:-1:-1;;26018:1:1;26000:16;;25993:27;25823:205::o;26033:136::-;;26100:5;26090:2;;26109:18;;:::i;:::-;-1:-1:-1;;;26145:18:1;;26080:89::o;26174:135::-;;-1:-1:-1;;26234:17:1;;26231:2;;;26254:18;;:::i;:::-;-1:-1:-1;26301:1:1;26290:13;;26221:88::o;26314:184::-;-1:-1:-1;;;26363:1:1;26356:88;26463:4;26460:1;26453:15;26487:4;26484:1;26477:15;26503:184;-1:-1:-1;;;26552:1:1;26545:88;26652:4;26649:1;26642:15;26676:4;26673:1;26666:15;26692:156;-1:-1:-1;;;;;26773:5:1;26769:54;26762:5;26759:65;26749:2;;26838:1;26835;26828:12;26853:120;26941:5;26934:13;26927:21;26920:5;26917:32;26907:2;;26963:1;26960;26953:12

Swarm Source

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