ETH Price: $2,283.60 (+2.29%)

Token

THE END IS NEAR (NEAR)
 

Overview

Max Total Supply

100,000,000 NEAR

Holders

11

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
*不打扰是我最后的温柔.eth
Balance
491,542.545346811352626293 NEAR

Value
$0.00
0xf70D9A2516dA5A22Bc103cd8d32EC221D726E500
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:
THEENDISNEAR

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-06-24
*/

// File: @openzeppelin/[email protected]/interfaces/IERC3156FlashBorrower.sol


// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC3156FlashBorrower.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC3156 FlashBorrower, as defined in
 * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
 *
 * _Available since v4.1._
 */
interface IERC3156FlashBorrower {
    /**
     * @dev Receive a flash loan.
     * @param initiator The initiator of the loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param fee The additional amount of tokens to repay.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
     */
    function onFlashLoan(
        address initiator,
        address token,
        uint256 amount,
        uint256 fee,
        bytes calldata data
    ) external returns (bytes32);
}

// File: @openzeppelin/[email protected]/interfaces/IERC3156FlashLender.sol


// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashLender.sol)

pragma solidity ^0.8.0;


/**
 * @dev Interface of the ERC3156 FlashLender, as defined in
 * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
 *
 * _Available since v4.1._
 */
interface IERC3156FlashLender {
    /**
     * @dev The amount of currency available to be lended.
     * @param token The loan currency.
     * @return The amount of `token` that can be borrowed.
     */
    function maxFlashLoan(address token) external view returns (uint256);

    /**
     * @dev The fee to be charged for a given loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function flashFee(address token, uint256 amount) external view returns (uint256);

    /**
     * @dev Initiate a flash loan.
     * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     */
    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external returns (bool);
}

// File: @openzeppelin/[email protected]/utils/math/SafeCast.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

// File: @openzeppelin/[email protected]/interfaces/IERC6372.sol


// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol)

pragma solidity ^0.8.0;

interface IERC6372 {
    /**
     * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
     */
    function clock() external view returns (uint48);

    /**
     * @dev Description of the clock
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() external view returns (string memory);
}

// File: @openzeppelin/[email protected]/governance/utils/IVotes.sol


// OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol)
pragma solidity ^0.8.0;

/**
 * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
 *
 * _Available since v4.5._
 */
interface IVotes {
    /**
     * @dev Emitted when an account changes their delegate.
     */
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /**
     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
     */
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) external view returns (uint256);

    /**
     * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value at the end of the corresponding block.
     */
    function getPastVotes(address account, uint256 timepoint) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value at the end of the corresponding block.
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     */
    function getPastTotalSupply(uint256 timepoint) external view returns (uint256);

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) external view returns (address);

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) external;

    /**
     * @dev Delegates votes from signer to `delegatee`.
     */
    function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
}

// File: @openzeppelin/[email protected]/interfaces/IERC5805.sol


// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5805.sol)

pragma solidity ^0.8.0;



interface IERC5805 is IERC6372, IVotes {}

// File: @openzeppelin/[email protected]/interfaces/IERC5267.sol


// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)

pragma solidity ^0.8.0;

interface IERC5267 {
    /**
     * @dev MAY be emitted to signal that the domain could have changed.
     */
    event EIP712DomainChanged();

    /**
     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
     * signature.
     */
    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}

// File: @openzeppelin/[email protected]/utils/math/SignedMath.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.0;

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

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

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/IERC20Permit.sol


// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

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

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

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

// File: @openzeppelin/[email protected]/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/[email protected]/utils/math/Math.sol


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/[email protected]/utils/Strings.sol


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

pragma solidity ^0.8.0;



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

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

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

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

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

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

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

// File: @openzeppelin/[email protected]/utils/cryptography/ECDSA.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;


/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, hash)
            message := keccak256(0x00, 0x3c)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, "\x19\x01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            data := keccak256(ptr, 0x42)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Data with intended validator, created from a
     * `validator` and `data` according to the version 0 of EIP-191.
     *
     * See {recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x00", validator, data));
    }
}

// File: @openzeppelin/[email protected]/utils/StorageSlot.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

// File: @openzeppelin/[email protected]/utils/ShortStrings.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol)

pragma solidity ^0.8.8;


// | string  | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA   |
// | length  | 0x                                                              BB |
type ShortString is bytes32;

/**
 * @dev This library provides functions to convert short memory strings
 * into a `ShortString` type that can be used as an immutable variable.
 *
 * Strings of arbitrary length can be optimized using this library if
 * they are short enough (up to 31 bytes) by packing them with their
 * length (1 byte) in a single EVM word (32 bytes). Additionally, a
 * fallback mechanism can be used for every other case.
 *
 * Usage example:
 *
 * ```solidity
 * contract Named {
 *     using ShortStrings for *;
 *
 *     ShortString private immutable _name;
 *     string private _nameFallback;
 *
 *     constructor(string memory contractName) {
 *         _name = contractName.toShortStringWithFallback(_nameFallback);
 *     }
 *
 *     function name() external view returns (string memory) {
 *         return _name.toStringWithFallback(_nameFallback);
 *     }
 * }
 * ```
 */
library ShortStrings {
    // Used as an identifier for strings longer than 31 bytes.
    bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;

    error StringTooLong(string str);
    error InvalidShortString();

    /**
     * @dev Encode a string of at most 31 chars into a `ShortString`.
     *
     * This will trigger a `StringTooLong` error is the input string is too long.
     */
    function toShortString(string memory str) internal pure returns (ShortString) {
        bytes memory bstr = bytes(str);
        if (bstr.length > 31) {
            revert StringTooLong(str);
        }
        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
    }

    /**
     * @dev Decode a `ShortString` back to a "normal" string.
     */
    function toString(ShortString sstr) internal pure returns (string memory) {
        uint256 len = byteLength(sstr);
        // using `new string(len)` would work locally but is not memory safe.
        string memory str = new string(32);
        /// @solidity memory-safe-assembly
        assembly {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

    /**
     * @dev Return the length of a `ShortString`.
     */
    function byteLength(ShortString sstr) internal pure returns (uint256) {
        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
        if (result > 31) {
            revert InvalidShortString();
        }
        return result;
    }

    /**
     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
     */
    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
        if (bytes(value).length < 32) {
            return toShortString(value);
        } else {
            StorageSlot.getStringSlot(store).value = value;
            return ShortString.wrap(_FALLBACK_SENTINEL);
        }
    }

    /**
     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     */
    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
            return toString(value);
        } else {
            return store;
        }
    }

    /**
     * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     *
     * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
     * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
     */
    function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
            return byteLength(value);
        } else {
            return bytes(store).length;
        }
    }
}

// File: @openzeppelin/[email protected]/utils/cryptography/EIP712.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.8;




/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
 * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the
 * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
 *
 * _Available since v3.4._
 *
 * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
 */
abstract contract EIP712 is IERC5267 {
    using ShortStrings for *;

    bytes32 private constant _TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    ShortString private immutable _name;
    ShortString private immutable _version;
    string private _nameFallback;
    string private _versionFallback;

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        _name = name.toShortStringWithFallback(_nameFallback);
        _version = version.toShortStringWithFallback(_versionFallback);
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
            return _cachedDomainSeparator;
        } else {
            return _buildDomainSeparator();
        }
    }

    function _buildDomainSeparator() private view returns (bytes32) {
        return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @dev See {EIP-5267}.
     *
     * _Available since v4.9._
     */
    function eip712Domain()
        public
        view
        virtual
        override
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f", // 01111
            _name.toStringWithFallback(_nameFallback),
            _version.toStringWithFallback(_versionFallback),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }
}

// File: @openzeppelin/[email protected]/utils/Arrays.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/Arrays.sol)

pragma solidity ^0.8.0;



/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
    using StorageSlot for bytes32;

    /**
     * @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 (unsafeAccess(array, mid).value > 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 && unsafeAccess(array, low - 1).value == element) {
            return low - 1;
        } else {
            return low;
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
        bytes32 slot;
        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getAddressSlot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
        bytes32 slot;
        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getBytes32Slot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
        bytes32 slot;
        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getUint256Slot();
    }
}

// File: @openzeppelin/[email protected]/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/[email protected]/security/Pausable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;


/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// File: @openzeppelin/[email protected]/access/Ownable.sol


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

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        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/[email protected]/token/ERC20/IERC20.sol


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

// File: @openzeppelin/[email protected]/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/[email protected]/token/ERC20/ERC20.sol


// OpenZeppelin Contracts (last updated v4.9.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.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of 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}.
     *
     * 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 default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

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

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

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

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

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

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

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

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

        return true;
    }

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

        _beforeTokenTransfer(from, to, amount);

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

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20FlashMint.sol


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/ERC20FlashMint.sol)

pragma solidity ^0.8.0;




/**
 * @dev Implementation of the ERC3156 Flash loans extension, as defined in
 * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
 *
 * Adds the {flashLoan} method, which provides flash loan support at the token
 * level. By default there is no fee, but this can be changed by overriding {flashFee}.
 *
 * _Available since v4.1._
 */
abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
    bytes32 private constant _RETURN_VALUE = keccak256("ERC3156FlashBorrower.onFlashLoan");

    /**
     * @dev Returns the maximum amount of tokens available for loan.
     * @param token The address of the token that is requested.
     * @return The amount of token that can be loaned.
     */
    function maxFlashLoan(address token) public view virtual override returns (uint256) {
        return token == address(this) ? type(uint256).max - ERC20.totalSupply() : 0;
    }

    /**
     * @dev Returns the fee applied when doing flash loans. This function calls
     * the {_flashFee} function which returns the fee applied when doing flash
     * loans.
     * @param token The token to be flash loaned.
     * @param amount The amount of tokens to be loaned.
     * @return The fees applied to the corresponding flash loan.
     */
    function flashFee(address token, uint256 amount) public view virtual override returns (uint256) {
        require(token == address(this), "ERC20FlashMint: wrong token");
        return _flashFee(token, amount);
    }

    /**
     * @dev Returns the fee applied when doing flash loans. By default this
     * implementation has 0 fees. This function can be overloaded to make
     * the flash loan mechanism deflationary.
     * @param token The token to be flash loaned.
     * @param amount The amount of tokens to be loaned.
     * @return The fees applied to the corresponding flash loan.
     */
    function _flashFee(address token, uint256 amount) internal view virtual returns (uint256) {
        // silence warning about unused variable without the addition of bytecode.
        token;
        amount;
        return 0;
    }

    /**
     * @dev Returns the receiver address of the flash fee. By default this
     * implementation returns the address(0) which means the fee amount will be burnt.
     * This function can be overloaded to change the fee receiver.
     * @return The address for which the flash fee will be sent to.
     */
    function _flashFeeReceiver() internal view virtual returns (address) {
        return address(0);
    }

    /**
     * @dev Performs a flash loan. New tokens are minted and sent to the
     * `receiver`, who is required to implement the {IERC3156FlashBorrower}
     * interface. By the end of the flash loan, the receiver is expected to own
     * amount + fee tokens and have them approved back to the token contract itself so
     * they can be burned.
     * @param receiver The receiver of the flash loan. Should implement the
     * {IERC3156FlashBorrower-onFlashLoan} interface.
     * @param token The token to be flash loaned. Only `address(this)` is
     * supported.
     * @param amount The amount of tokens to be loaned.
     * @param data An arbitrary datafield that is passed to the receiver.
     * @return `true` if the flash loan was successful.
     */
    // This function can reenter, but it doesn't pose a risk because it always preserves the property that the amount
    // minted at the beginning is always recovered and burned at the end, or else the entire function will revert.
    // slither-disable-next-line reentrancy-no-eth
    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) public virtual override returns (bool) {
        require(amount <= maxFlashLoan(token), "ERC20FlashMint: amount exceeds maxFlashLoan");
        uint256 fee = flashFee(token, amount);
        _mint(address(receiver), amount);
        require(
            receiver.onFlashLoan(msg.sender, token, amount, fee, data) == _RETURN_VALUE,
            "ERC20FlashMint: invalid return value"
        );
        address flashFeeReceiver = _flashFeeReceiver();
        _spendAllowance(address(receiver), address(this), amount + fee);
        if (fee == 0 || flashFeeReceiver == address(0)) {
            _burn(address(receiver), amount + fee);
        } else {
            _burn(address(receiver), amount);
            _transfer(address(receiver), flashFeeReceiver, fee);
        }
        return true;
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Permit.sol


// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Permit.sol)

pragma solidity ^0.8.0;






/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

    mapping(address => Counters.Counter) private _nonces;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private constant _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    /**
     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
     * However, to ensure consistency with the upgradeable transpiler, we will continue
     * to reserve a slot.
     * @custom:oz-renamed-from _PERMIT_TYPEHASH
     */
    // solhint-disable-next-line var-name-mixedcase
    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC20 token name.
     */
    constructor(string memory name) EIP712(name, "1") {}

    /**
     * @dev See {IERC20Permit-permit}.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, "ERC20Permit: invalid signature");

        _approve(owner, spender, value);
    }

    /**
     * @dev See {IERC20Permit-nonces}.
     */
    function nonces(address owner) public view virtual override returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev "Consume a nonce": return the current value and increment.
     *
     * _Available since v4.1._
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Votes.sol


// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Votes.sol)

pragma solidity ^0.8.0;






/**
 * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,
 * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.
 *
 * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.
 *
 * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
 * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
 * power can be queried through the public accessors {getVotes} and {getPastVotes}.
 *
 * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
 * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
 *
 * _Available since v4.2._
 */
abstract contract ERC20Votes is ERC20Permit, IERC5805 {
    struct Checkpoint {
        uint32 fromBlock;
        uint224 votes;
    }

    bytes32 private constant _DELEGATION_TYPEHASH =
        keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    mapping(address => address) private _delegates;
    mapping(address => Checkpoint[]) private _checkpoints;
    Checkpoint[] private _totalSupplyCheckpoints;

    /**
     * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
     */
    function clock() public view virtual override returns (uint48) {
        return SafeCast.toUint48(block.number);
    }

    /**
     * @dev Description of the clock
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() public view virtual override returns (string memory) {
        // Check that the clock was not modified
        require(clock() == block.number, "ERC20Votes: broken clock mode");
        return "mode=blocknumber&from=default";
    }

    /**
     * @dev Get the `pos`-th checkpoint for `account`.
     */
    function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {
        return _checkpoints[account][pos];
    }

    /**
     * @dev Get number of checkpoints for `account`.
     */
    function numCheckpoints(address account) public view virtual returns (uint32) {
        return SafeCast.toUint32(_checkpoints[account].length);
    }

    /**
     * @dev Get the address `account` is currently delegating to.
     */
    function delegates(address account) public view virtual override returns (address) {
        return _delegates[account];
    }

    /**
     * @dev Gets the current votes balance for `account`
     */
    function getVotes(address account) public view virtual override returns (uint256) {
        uint256 pos = _checkpoints[account].length;
        unchecked {
            return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
        }
    }

    /**
     * @dev Retrieve the number of votes for `account` at the end of `timepoint`.
     *
     * Requirements:
     *
     * - `timepoint` must be in the past
     */
    function getPastVotes(address account, uint256 timepoint) public view virtual override returns (uint256) {
        require(timepoint < clock(), "ERC20Votes: future lookup");
        return _checkpointsLookup(_checkpoints[account], timepoint);
    }

    /**
     * @dev Retrieve the `totalSupply` at the end of `timepoint`. Note, this value is the sum of all balances.
     * It is NOT the sum of all the delegated votes!
     *
     * Requirements:
     *
     * - `timepoint` must be in the past
     */
    function getPastTotalSupply(uint256 timepoint) public view virtual override returns (uint256) {
        require(timepoint < clock(), "ERC20Votes: future lookup");
        return _checkpointsLookup(_totalSupplyCheckpoints, timepoint);
    }

    /**
     * @dev Lookup a value in a list of (sorted) checkpoints.
     */
    function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 timepoint) private view returns (uint256) {
        // We run a binary search to look for the last (most recent) checkpoint taken before (or at) `timepoint`.
        //
        // Initially we check if the block is recent to narrow the search range.
        // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).
        // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.
        // - If the middle checkpoint is after `timepoint`, we look in [low, mid)
        // - If the middle checkpoint is before or equal to `timepoint`, we look in [mid+1, high)
        // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not
        // out of bounds (in which case we're looking too far in the past and the result is 0).
        // Note that if the latest checkpoint available is exactly for `timepoint`, we end up with an index that is
        // past the end of the array, so we technically don't find a checkpoint after `timepoint`, but it works out
        // the same.
        uint256 length = ckpts.length;

        uint256 low = 0;
        uint256 high = length;

        if (length > 5) {
            uint256 mid = length - Math.sqrt(length);
            if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        unchecked {
            return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes;
        }
    }

    /**
     * @dev Delegate votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) public virtual override {
        _delegate(_msgSender(), delegatee);
    }

    /**
     * @dev Delegates votes from signer to `delegatee`
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= expiry, "ERC20Votes: signature expired");
        address signer = ECDSA.recover(
            _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
            v,
            r,
            s
        );
        require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce");
        _delegate(signer, delegatee);
    }

    /**
     * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).
     */
    function _maxSupply() internal view virtual returns (uint224) {
        return type(uint224).max;
    }

    /**
     * @dev Snapshots the totalSupply after it has been increased.
     */
    function _mint(address account, uint256 amount) internal virtual override {
        super._mint(account, amount);
        require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes");

        _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);
    }

    /**
     * @dev Snapshots the totalSupply after it has been decreased.
     */
    function _burn(address account, uint256 amount) internal virtual override {
        super._burn(account, amount);

        _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);
    }

    /**
     * @dev Move voting power when tokens are transferred.
     *
     * Emits a {IVotes-DelegateVotesChanged} event.
     */
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual override {
        super._afterTokenTransfer(from, to, amount);

        _moveVotingPower(delegates(from), delegates(to), amount);
    }

    /**
     * @dev Change delegation for `delegator` to `delegatee`.
     *
     * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
     */
    function _delegate(address delegator, address delegatee) internal virtual {
        address currentDelegate = delegates(delegator);
        uint256 delegatorBalance = balanceOf(delegator);
        _delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);

        _moveVotingPower(currentDelegate, delegatee, delegatorBalance);
    }

    function _moveVotingPower(address src, address dst, uint256 amount) private {
        if (src != dst && amount > 0) {
            if (src != address(0)) {
                (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);
                emit DelegateVotesChanged(src, oldWeight, newWeight);
            }

            if (dst != address(0)) {
                (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);
                emit DelegateVotesChanged(dst, oldWeight, newWeight);
            }
        }
    }

    function _writeCheckpoint(
        Checkpoint[] storage ckpts,
        function(uint256, uint256) view returns (uint256) op,
        uint256 delta
    ) private returns (uint256 oldWeight, uint256 newWeight) {
        uint256 pos = ckpts.length;

        unchecked {
            Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1);

            oldWeight = oldCkpt.votes;
            newWeight = op(oldWeight, delta);

            if (pos > 0 && oldCkpt.fromBlock == clock()) {
                _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight);
            } else {
                ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(clock()), votes: SafeCast.toUint224(newWeight)}));
            }
        }
    }

    function _add(uint256 a, uint256 b) private pure returns (uint256) {
        return a + b;
    }

    function _subtract(uint256 a, uint256 b) private pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
     */
    function _unsafeAccess(Checkpoint[] storage ckpts, uint256 pos) private pure returns (Checkpoint storage result) {
        assembly {
            mstore(0, ckpts.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/draft-ERC20Permit.sol


// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/draft-ERC20Permit.sol)

pragma solidity ^0.8.0;

// EIP-2612 is Final as of 2022-11-01. This file is deprecated.


// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Snapshot.sol


// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Snapshot.sol)

pragma solidity ^0.8.0;




/**
 * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and
 * total supply at the time are recorded for later access.
 *
 * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting.
 * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different
 * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be
 * used to create an efficient ERC20 forking mechanism.
 *
 * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a
 * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot
 * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id
 * and the account address.
 *
 * NOTE: Snapshot policy can be customized by overriding the {_getCurrentSnapshotId} method. For example, having it
 * return `block.number` will trigger the creation of snapshot at the beginning of each new block. When overriding this
 * function, be careful about the monotonicity of its result. Non-monotonic snapshot ids will break the contract.
 *
 * Implementing snapshots for every block using this method will incur significant gas costs. For a gas-efficient
 * alternative consider {ERC20Votes}.
 *
 * ==== Gas Costs
 *
 * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log
 * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much
 * smaller since identical balances in subsequent snapshots are stored as a single entry.
 *
 * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is
 * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent
 * transfers will have normal cost until the next snapshot, and so on.
 */

abstract contract ERC20Snapshot is ERC20 {
    // Inspired by Jordi Baylina's MiniMeToken to record historical balances:
    // https://github.com/Giveth/minime/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol

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

    // Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a
    // Snapshot struct, but that would impede usage of functions that work on an array.
    struct Snapshots {
        uint256[] ids;
        uint256[] values;
    }

    mapping(address => Snapshots) private _accountBalanceSnapshots;
    Snapshots private _totalSupplySnapshots;

    // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
    Counters.Counter private _currentSnapshotId;

    /**
     * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created.
     */
    event Snapshot(uint256 id);

    /**
     * @dev Creates a new snapshot and returns its snapshot id.
     *
     * Emits a {Snapshot} event that contains the same id.
     *
     * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a
     * set of accounts, for example using {AccessControl}, or it may be open to the public.
     *
     * [WARNING]
     * ====
     * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking,
     * you must consider that it can potentially be used by attackers in two ways.
     *
     * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow
     * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target
     * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs
     * section above.
     *
     * We haven't measured the actual numbers; if this is something you're interested in please reach out to us.
     * ====
     */
    function _snapshot() internal virtual returns (uint256) {
        _currentSnapshotId.increment();

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

    /**
     * @dev Get the current snapshotId
     */
    function _getCurrentSnapshotId() internal view virtual returns (uint256) {
        return _currentSnapshotId.current();
    }

    /**
     * @dev Retrieves the balance of `account` at the time `snapshotId` was created.
     */
    function balanceOfAt(address account, uint256 snapshotId) public view virtual returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);

        return snapshotted ? value : balanceOf(account);
    }

    /**
     * @dev Retrieves the total supply at the time `snapshotId` was created.
     */
    function totalSupplyAt(uint256 snapshotId) public view virtual returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);

        return snapshotted ? value : totalSupply();
    }

    // Update balance and/or total supply snapshots before the values are modified. This is implemented
    // in the _beforeTokenTransfer hook, which is executed for _mint, _burn, and _transfer operations.
    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);
        }
    }

    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");

        // When a valid snapshot is queried, there are three possibilities:
        //  a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
        //  created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
        //  to this id is the current one.
        //  b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
        //  requested id, and its value is the one to return.
        //  c) More snapshots were created after the requested one, and the queried value was later modified. There will be
        //  no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
        //  larger than the requested one.
        //
        // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
        // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
        // exactly this.

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

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

    function _updateAccountSnapshot(address account) private {
        _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
    }

    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];
        }
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Burnable.sol


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

pragma solidity ^0.8.0;



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

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public virtual {
        _spendAllowance(account, _msgSender(), amount);
        _burn(account, amount);
    }
}

// File: contract-60caae0b8e.sol


pragma solidity ^0.8.9;









contract THEENDISNEAR is ERC20, ERC20Burnable, ERC20Snapshot, Ownable, Pausable, ERC20Permit, ERC20Votes, ERC20FlashMint {
    constructor()
        ERC20("THE END IS NEAR", "NEAR")
        ERC20Permit("THE END IS NEAR")
    {
        _mint(msg.sender, 100000000 * 10 ** decimals());
    }

    function snapshot() public onlyOwner {
        _snapshot();
    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

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

    // The following functions are overrides required by Solidity.

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

    function _mint(address to, uint256 amount)
        internal
        override(ERC20, ERC20Votes)
    {
        super._mint(to, amount);
    }

    function _burn(address account, uint256 amount)
        internal
        override(ERC20, ERC20Votes)
    {
        super._burn(account, amount);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"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":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","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":"account","type":"address"},{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32","name":"pos","type":"uint32"}],"name":"checkpoints","outputs":[{"components":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint224","name":"votes","type":"uint224"}],"internalType":"struct ERC20Votes.Checkpoint","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"flashFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC3156FlashBorrower","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"maxFlashLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","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":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"snapshot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101606040523480156200001257600080fd5b506040518060400160405280600f81526020016e2a24229022a7221024a9902722a0a960891b81525080604051806040016040528060018152602001603160f81b8152506040518060400160405280600f81526020016e2a24229022a7221024a9902722a0a960891b815250604051806040016040528060048152602001632722a0a960e11b8152508160039080519060200190620000b392919062000b47565b508051620000c990600490602084019062000b47565b505050620000e6620000e0620001f060201b60201c565b620001f4565b6009805460ff60a01b191690556200010c82600a62000246602090811b6200116417901c565b610120526200012981600b62000246602090811b6200116417901c565b61014052815160208084019190912060e052815190820120610100524660a052620001b760e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c05250620001ea33620001d46012600a62000cf6565b620001e4906305f5e10062000d07565b6200029a565b62000e2b565b3390565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600060208351101562000266576200025e83620002b5565b905062000294565b826200027d836200030160201b6200119b1760201c565b81516200028e926020019062000b47565b5060ff90505b92915050565b620002b182826200030460201b6200119e1760201c565b5050565b600080829050601f81511115620002ec578260405163305a27a960e01b8152600401620002e3919062000d29565b60405180910390fd5b8051620002f98262000d81565b179392505050565b90565b6200031b8282620003b760201b6200122e1760201c565b6001600160e01b036200032f620004928216565b1115620003985760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b6064820152608401620002e3565b620003b16010620013016200049860201b1783620004ad565b50505050565b6001600160a01b0382166200040f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401620002e3565b6200041d6000838362000656565b806002600082825462000431919062000da9565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3620002b1600083836200067d565b60025490565b6000620004a6828462000da9565b9392505050565b82546000908190818115620004fc5760008781526020902082016000190160408051808201909152905463ffffffff8116825264010000000090046001600160e01b0316602082015262000511565b60408051808201909152600080825260208201525b905080602001516001600160e01b031693506200052f84868860201c565b92506000821180156200055c57506200054762000695565b65ffffffffffff16816000015163ffffffff16145b15620005b0576200057883620006b260201b6200130d1760201c565b60008881526020902083016000190180546001600160e01b03929092166401000000000263ffffffff9092169190911790556200064c565b866040518060400160405280620005e9620005d06200069560201b60201c565b65ffffffffffff166200072160201b6200137a1760201c565b63ffffffff1681526020016200060a86620006b260201b6200130d1760201c565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b5050935093915050565b6200066062000788565b62000678838383620007e060201b620013df1760201c565b505050565b620006788383836200084c60201b6200142c1760201c565b6000620006ad436200089860201b6200145e1760201c565b905090565b60006001600160e01b038211156200071d5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401620002e3565b5090565b600063ffffffff8211156200071d5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401620002e3565b6200079c600954600160a01b900460ff1690565b15620007de5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401620002e3565b565b620007f88383836200067860201b620013fe1760201c565b6001600160a01b0383166200081c57620008128262000901565b6200067862000939565b6001600160a01b0382166200083657620008128362000901565b620008418362000901565b620006788262000901565b620008648383836200067860201b620013fe1760201c565b6001600160a01b038381166000908152600e6020526040808220548584168352912054620006789291821691168362000949565b600065ffffffffffff8211156200071d5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401620002e3565b6001600160a01b0381166000908152600560209081526040808320918390529091205462000936919062000a84565b62000a84565b50565b620007de60066200093060025490565b816001600160a01b0316836001600160a01b0316141580156200096c5750600081115b1562000678576001600160a01b03831615620009f9576001600160a01b0383166000908152600f6020908152604082208291620009b6919062000ad3901b620014c51785620004ad565b91509150846001600160a01b031660008051602062003d858339815191528383604051620009ee929190918252602082015260400190565b60405180910390a250505b6001600160a01b0382161562000678576001600160a01b0382166000908152600f602090815260408220829162000a3d919062000498901b620013011785620004ad565b91509150836001600160a01b031660008051602062003d85833981519152838360405162000a75929190918252602082015260400190565b60405180910390a25050505050565b600062000a9062000ae1565b90508062000a9e8462000afa565b101562000678578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b6000620004a6828462000dc4565b6000620006ad600862000b4360201b620014d11760201c565b805460009062000b0c57506000919050565b8154829062000b1e9060019062000dc4565b8154811062000b315762000b3162000dde565b90600052602060002001549050919050565b5490565b82805462000b559062000df4565b90600052602060002090601f01602090048101928262000b79576000855562000bc4565b82601f1062000b9457805160ff191683800117855562000bc4565b8280016001018555821562000bc4579182015b8281111562000bc457825182559160200191906001019062000ba7565b506200071d9291505b808211156200071d576000815560010162000bcd565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000c3a57816000190482111562000c1e5762000c1e62000be3565b8085161562000c2c57918102915b93841c939080029062000bfe565b509250929050565b60008262000c535750600162000294565b8162000c625750600062000294565b816001811462000c7b576002811462000c865762000ca6565b600191505062000294565b60ff84111562000c9a5762000c9a62000be3565b50506001821b62000294565b5060208310610133831016604e8410600b841016171562000ccb575081810a62000294565b62000cd7838362000bf9565b806000190482111562000cee5762000cee62000be3565b029392505050565b6000620004a660ff84168362000c42565b600081600019048311821515161562000d245762000d2462000be3565b500290565b600060208083528351808285015260005b8181101562000d585785810183015185820160400152820162000d3a565b8181111562000d6b576000604083870101525b50601f01601f1916929092016040019392505050565b8051602080830151919081101562000da3576000198160200360031b1b821691505b50919050565b6000821982111562000dbf5762000dbf62000be3565b500190565b60008282101562000dd95762000dd962000be3565b500390565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000e0957607f821691505b6020821081141562000da357634e487b7160e01b600052602260045260246000fd5b60805160a05160c05160e051610100516101205161014051612eff62000e866000396000610b2d01526000610b02015260006118fc015260006118d40152600061182f01526000611859015260006118830152612eff6000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c8063715018a61161013b578063981b24d0116100b8578063d505accf1161007c578063d505accf1461051e578063d9d98ce414610531578063dd62ed3e14610544578063f1127ed814610557578063f2fde38b1461059457600080fd5b8063981b24d0146104bf5780639ab24eb0146104d2578063a457c2d7146104e5578063a9059cbb146104f8578063c3cda5201461050b57600080fd5b80638da5cb5b116100ff5780638da5cb5b1461046c5780638e539e8c1461047d57806391ddadf41461049057806395d89b41146104af5780639711715a146104b757600080fd5b8063715018a61461041b57806379cc6790146104235780637ecebe00146104365780638456cb591461044957806384b0196e1461045157600080fd5b806342966c68116101c95780635c975abb1161018d5780635c975abb146103925780635cffe9de146103a4578063613255ab146103b75780636fcfff45146103ca57806370a08231146103f257600080fd5b806342966c681461030d5780634bf5d7e9146103205780634ee2cd7e14610328578063587cde1e1461033b5780635c19a95c1461037f57600080fd5b80633644e515116102105780633644e515146102c257806339509351146102ca5780633a46b1a8146102dd5780633f4ba83a146102f057806340c10f19146102fa57600080fd5b806306fdde031461024d578063095ea7b31461026b57806318160ddd1461028e57806323b872dd146102a0578063313ce567146102b3575b600080fd5b6102556105a7565b6040516102629190612a09565b60405180910390f35b61027e610279366004612a31565b610639565b6040519015158152602001610262565b6002545b604051908152602001610262565b61027e6102ae366004612a5d565b610653565b60405160128152602001610262565b610292610677565b61027e6102d8366004612a31565b610686565b6102926102eb366004612a31565b6106a8565b6102f8610732565b005b6102f8610308366004612a31565b610744565b6102f861031b366004612a9e565b61075a565b610255610767565b610292610336366004612a31565b6107ff565b610367610349366004612ab7565b6001600160a01b039081166000908152600e60205260409020541690565b6040516001600160a01b039091168152602001610262565b6102f861038d366004612ab7565b610858565b600954600160a01b900460ff1661027e565b61027e6103b2366004612ad4565b610862565b6102926103c5366004612ab7565b610a55565b6103dd6103d8366004612ab7565b610a7d565b60405163ffffffff9091168152602001610262565b610292610400366004612ab7565b6001600160a01b031660009081526020819052604090205490565b6102f8610a9f565b6102f8610431366004612a31565b610ab1565b610292610444366004612ab7565b610ac6565b6102f8610ae4565b610459610af4565b6040516102629796959493929190612b73565b6009546001600160a01b0316610367565b61029261048b366004612a9e565b610b7d565b610498610be4565b60405165ffffffffffff9091168152602001610262565b610255610bef565b6102f8610bfe565b6102926104cd366004612a9e565b610c0e565b6102926104e0366004612ab7565b610c39565b61027e6104f3366004612a31565b610cbb565b61027e610506366004612a31565b610d36565b6102f8610519366004612c1a565b610d44565b6102f861052c366004612c74565b610e7a565b61029261053f366004612a31565b610fde565b610292610552366004612ce2565b61103f565b61056a610565366004612d1b565b61106a565b60408051825163ffffffff1681526020928301516001600160e01b03169281019290925201610262565b6102f86105a2366004612ab7565b6110ee565b6060600380546105b690612d52565b80601f01602080910402602001604051908101604052809291908181526020018280546105e290612d52565b801561062f5780601f106106045761010080835404028352916020019161062f565b820191906000526020600020905b81548152906001019060200180831161061257829003601f168201915b5050505050905090565b6000336106478185856114d5565b60019150505b92915050565b6000336106618582856115f9565b61066c85858561166d565b506001949350505050565b6000610681611822565b905090565b600033610647818585610699838361103f565b6106a39190612d9d565b6114d5565b60006106b2610be4565b65ffffffffffff1682106107095760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b60448201526064015b60405180910390fd5b6001600160a01b0383166000908152600f6020526040902061072b908361194d565b9392505050565b61073a611a36565b610742611a90565b565b61074c611a36565b6107568282611ae5565b5050565b6107643382611aef565b50565b606043610772610be4565b65ffffffffffff16146107c75760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a2062726f6b656e20636c6f636b206d6f64650000006044820152606401610700565b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b6001600160a01b038216600090815260056020526040812081908190610826908590611af9565b915091508161084d576001600160a01b03851660009081526020819052604090205461084f565b805b95945050505050565b6107643382611bf0565b600061086d85610a55565b8411156108d05760405162461bcd60e51b815260206004820152602b60248201527f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60448201526a30bc233630b9b42637b0b760a91b6064820152608401610700565b60006108dc8686610fde565b90506108e88786611ae5565b6040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038916906323e30c8b906109409033908b908b9088908c908c90600401612db5565b602060405180830381600087803b15801561095a57600080fd5b505af115801561096e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109929190612e11565b146109eb5760405162461bcd60e51b8152602060048201526024808201527f4552433230466c6173684d696e743a20696e76616c69642072657475726e2076604482015263616c756560e01b6064820152608401610700565b6000610a0188306109fc858a612d9d565b6115f9565b811580610a1557506001600160a01b038116155b15610a3257610a2d88610a288489612d9d565b611aef565b610a47565b610a3c8887611aef565b610a4788828461166d565b506001979650505050505050565b60006001600160a01b0382163014610a6e57600061064d565b60025461064d90600019612e2a565b6001600160a01b0381166000908152600f602052604081205461064d9061137a565b610aa7611a36565b6107426000611c69565b610abc8233836115f9565b6107568282611aef565b6001600160a01b0381166000908152600c602052604081205461064d565b610aec611a36565b610742611cbb565b600060608082808083610b287f0000000000000000000000000000000000000000000000000000000000000000600a611cfe565b610b537f0000000000000000000000000000000000000000000000000000000000000000600b611cfe565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6000610b87610be4565b65ffffffffffff168210610bd95760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b6044820152606401610700565b61064d60108361194d565b60006106814361145e565b6060600480546105b690612d52565b610c06611a36565b610764611da2565b6000806000610c1e846006611af9565b9150915081610c2f57600254610c31565b805b949350505050565b6001600160a01b0381166000908152600f60205260408120548015610ca8576001600160a01b0383166000908152600f6020526040902080546000198301908110610c8657610c86612e41565b60009182526020909120015464010000000090046001600160e01b0316610cab565b60005b6001600160e01b03169392505050565b60003381610cc9828661103f565b905083811015610d295760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610700565b61066c82868684036114d5565b60003361064781858561166d565b83421115610d945760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a207369676e617475726520657870697265640000006044820152606401610700565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090610e0e90610e069060a00160405160208183030381529060405280519060200120611dfc565b858585611e29565b9050610e1981611e51565b8614610e675760405162461bcd60e51b815260206004820152601960248201527f4552433230566f7465733a20696e76616c6964206e6f6e6365000000000000006044820152606401610700565b610e718188611bf0565b50505050505050565b83421115610eca5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610700565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610ef98c611e51565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610f5482611dfc565b90506000610f6482878787611e29565b9050896001600160a01b0316816001600160a01b031614610fc75760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610700565b610fd28a8a8a6114d5565b50505050505050505050565b60006001600160a01b03831630146110385760405162461bcd60e51b815260206004820152601b60248201527f4552433230466c6173684d696e743a2077726f6e6720746f6b656e00000000006044820152606401610700565b600061072b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60408051808201909152600080825260208201526001600160a01b0383166000908152600f60205260409020805463ffffffff84169081106110ae576110ae612e41565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160e01b0316918101919091529392505050565b6110f6611a36565b6001600160a01b03811661115b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610700565b61076481611c69565b60006020835110156111805761117983611e79565b905061064d565b82828151611191926020019061292c565b5060ff905061064d565b90565b6111a8828261122e565b6002546001600160e01b03101561121a5760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b6064820152608401610700565b611228601061130183611eb7565b50505050565b6001600160a01b0382166112845760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610700565b6112906000838361202c565b80600260008282546112a29190612d9d565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36107566000838361203f565b600061072b8284612d9d565b60006001600160e01b038211156113765760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610700565b5090565b600063ffffffff8211156113765760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610700565b6001600160a01b038316611403576113f68261204a565b6113fe61207c565b505050565b6001600160a01b03821661141a576113f68361204a565b6114238361204a565b6113fe8261204a565b6001600160a01b038381166000908152600e60205260408082205485841683529120546113fe9291821691168361208a565b600065ffffffffffff8211156113765760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610700565b600061072b8284612e2a565b5490565b6001600160a01b0383166115375760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610700565b6001600160a01b0382166115985760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610700565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000611605848461103f565b9050600019811461122857818110156116605760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610700565b61122884848484036114d5565b6001600160a01b0383166116d15760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610700565b6001600160a01b0382166117335760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610700565b61173e83838361202c565b6001600160a01b038316600090815260208190526040902054818110156117b65760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610700565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361122884848461203f565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561187b57507f000000000000000000000000000000000000000000000000000000000000000046145b156118a557507f000000000000000000000000000000000000000000000000000000000000000090565b610681604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b8154600090818160058111156119a7576000611968846121c7565b6119729085612e2a565b600088815260209020909150869082015463ffffffff161115611997578091506119a5565b6119a2816001612d9d565b92505b505b808210156119f45760006119bb83836122ac565b600088815260209020909150869082015463ffffffff1611156119e0578091506119ee565b6119eb816001612d9d565b92505b506119a7565b8015611a20576000868152602090208101600019015464010000000090046001600160e01b0316611a23565b60005b6001600160e01b03169695505050505050565b6009546001600160a01b031633146107425760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610700565b611a986122c7565b6009805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b610756828261119e565b6107568282612317565b60008060008411611b455760405162461bcd60e51b815260206004820152601660248201527504552433230536e617073686f743a20696420697320360541b6044820152606401610700565b611b4d61232f565b841115611b9c5760405162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e742069640000006044820152606401610700565b6000611ba8848661233a565b8454909150811415611bc1576000809250925050611be9565b6001846001018281548110611bd857611bd8612e41565b906000526020600020015492509250505b9250929050565b6001600160a01b038281166000818152600e60208181526040808420805485845282862054949093528787166001600160a01b03198416811790915590519190951694919391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a461122882848361208a565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611cc36123e5565b6009805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611ac83390565b606060ff8314611d115761117983612432565b818054611d1d90612d52565b80601f0160208091040260200160405190810160405280929190818152602001828054611d4990612d52565b8015611d965780601f10611d6b57610100808354040283529160200191611d96565b820191906000526020600020905b815481529060010190602001808311611d7957829003601f168201915b5050505050905061064d565b6000611db2600880546001019055565b6000611dbc61232f565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb6781604051611def91815260200190565b60405180910390a1919050565b600061064d611e09611822565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000611e3a87878787612471565b91509150611e4781612535565b5095945050505050565b6001600160a01b0381166000908152600c602052604090208054600181018255905b50919050565b600080829050601f81511115611ea4578260405163305a27a960e01b81526004016107009190612a09565b8051611eaf82612e57565b179392505050565b82546000908190818115611f045760008781526020902082016000190160408051808201909152905463ffffffff8116825264010000000090046001600160e01b03166020820152611f19565b60408051808201909152600080825260208201525b905080602001516001600160e01b03169350611f3984868863ffffffff16565b9250600082118015611f635750611f4e610be4565b65ffffffffffff16816000015163ffffffff16145b15611fa857611f718361130d565b60008881526020902083016000190180546001600160e01b03929092166401000000000263ffffffff909216919091179055612022565b866040518060400160405280611fcc611fbf610be4565b65ffffffffffff1661137a565b63ffffffff168152602001611fe08661130d565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b5050935093915050565b6120346123e5565b6113fe8383836113df565b6113fe83838361142c565b6001600160a01b038116600090815260056020908152604080832091839052909120546107649190612683565b612683565b610742600661207760025490565b816001600160a01b0316836001600160a01b0316141580156120ac5750600081115b156113fe576001600160a01b0383161561213a576001600160a01b0383166000908152600f6020526040812081906120e7906114c585611eb7565b91509150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405161212f929190918252602082015260400190565b60405180910390a250505b6001600160a01b038216156113fe576001600160a01b0382166000908152600f6020526040812081906121709061130185611eb7565b91509150836001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516121b8929190918252602082015260400190565b60405180910390a25050505050565b6000816121d657506000919050565b600060016121e3846126cd565b901c6001901b905060018184816121fc576121fc612e7b565b048201901c9050600181848161221457612214612e7b565b048201901c9050600181848161222c5761222c612e7b565b048201901c9050600181848161224457612244612e7b565b048201901c9050600181848161225c5761225c612e7b565b048201901c9050600181848161227457612274612e7b565b048201901c9050600181848161228c5761228c612e7b565b048201901c905061072b818285816122a6576122a6612e7b565b04612761565b60006122bb6002848418612e91565b61072b90848416612d9d565b600954600160a01b900460ff166107425760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610700565b6123218282612777565b61122860106114c583611eb7565b600061068160085490565b815460009061234b5750600061064d565b82546000905b8082101561239857600061236583836122ac565b6000878152602090209091508590820154111561238457809150612392565b61238f816001612d9d565b92505b50612351565b6000821180156123c45750836123c1866123b3600186612e2a565b600091825260209091200190565b54145b156123dd576123d4600183612e2a565b9250505061064d565b50905061064d565b600954600160a01b900460ff16156107425760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610700565b6060600061243f836128bc565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156124a8575060009050600361252c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156124fc573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166125255760006001925092505061252c565b9150600090505b94509492505050565b600081600481111561254957612549612eb3565b14156125525750565b600181600481111561256657612566612eb3565b14156125b45760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610700565b60028160048111156125c8576125c8612eb3565b14156126165760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610700565b600381600481111561262a5761262a612eb3565b14156107645760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610700565b600061268d61232f565b905080612699846128e4565b10156113fe578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b600080608083901c156126e257608092831c92015b604083901c156126f457604092831c92015b602083901c1561270657602092831c92015b601083901c1561271857601092831c92015b600883901c1561272a57600892831c92015b600483901c1561273c57600492831c92015b600283901c1561274e57600292831c92015b600183901c1561064d5760010192915050565b6000818310612770578161072b565b5090919050565b6001600160a01b0382166127d75760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610700565b6127e38260008361202c565b6001600160a01b038216600090815260208190526040902054818110156128575760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610700565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36113fe8360008461203f565b600060ff8216601f81111561064d57604051632cd44ac360e21b815260040160405180910390fd5b80546000906128f557506000919050565b8154829061290590600190612e2a565b8154811061291557612915612e41565b90600052602060002001549050919050565b919050565b82805461293890612d52565b90600052602060002090601f01602090048101928261295a57600085556129a0565b82601f1061297357805160ff19168380011785556129a0565b828001600101855582156129a0579182015b828111156129a0578251825591602001919060010190612985565b506113769291505b8082111561137657600081556001016129a8565b6000815180845260005b818110156129e2576020818501810151868301820152016129c6565b818111156129f4576000602083870101525b50601f01601f19169290920160200192915050565b60208152600061072b60208301846129bc565b6001600160a01b038116811461076457600080fd5b60008060408385031215612a4457600080fd5b8235612a4f81612a1c565b946020939093013593505050565b600080600060608486031215612a7257600080fd5b8335612a7d81612a1c565b92506020840135612a8d81612a1c565b929592945050506040919091013590565b600060208284031215612ab057600080fd5b5035919050565b600060208284031215612ac957600080fd5b813561072b81612a1c565b600080600080600060808688031215612aec57600080fd5b8535612af781612a1c565b94506020860135612b0781612a1c565b935060408601359250606086013567ffffffffffffffff80821115612b2b57600080fd5b818801915088601f830112612b3f57600080fd5b813581811115612b4e57600080fd5b896020828501011115612b6057600080fd5b9699959850939650602001949392505050565b60ff60f81b881681526000602060e081840152612b9360e084018a6129bc565b8381036040850152612ba5818a6129bc565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015612bf757835183529284019291840191600101612bdb565b50909c9b505050505050505050505050565b803560ff8116811461292757600080fd5b60008060008060008060c08789031215612c3357600080fd5b8635612c3e81612a1c565b95506020870135945060408701359350612c5a60608801612c09565b92506080870135915060a087013590509295509295509295565b600080600080600080600060e0888a031215612c8f57600080fd5b8735612c9a81612a1c565b96506020880135612caa81612a1c565b95506040880135945060608801359350612cc660808901612c09565b925060a0880135915060c0880135905092959891949750929550565b60008060408385031215612cf557600080fd5b8235612d0081612a1c565b91506020830135612d1081612a1c565b809150509250929050565b60008060408385031215612d2e57600080fd5b8235612d3981612a1c565b9150602083013563ffffffff81168114612d1057600080fd5b600181811c90821680612d6657607f821691505b60208210811415611e7357634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612db057612db0612d87565b500190565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c0840137600060c0848401015260c0601f19601f8501168301019050979650505050505050565b600060208284031215612e2357600080fd5b5051919050565b600082821015612e3c57612e3c612d87565b500390565b634e487b7160e01b600052603260045260246000fd5b80516020808301519190811015611e735760001960209190910360031b1b16919050565b634e487b7160e01b600052601260045260246000fd5b600082612eae57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220f22a03b5546797be6c1f2571a39a330ebdbf825b68d5917697b2972e0fc9ae5764736f6c63430008090033dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102485760003560e01c8063715018a61161013b578063981b24d0116100b8578063d505accf1161007c578063d505accf1461051e578063d9d98ce414610531578063dd62ed3e14610544578063f1127ed814610557578063f2fde38b1461059457600080fd5b8063981b24d0146104bf5780639ab24eb0146104d2578063a457c2d7146104e5578063a9059cbb146104f8578063c3cda5201461050b57600080fd5b80638da5cb5b116100ff5780638da5cb5b1461046c5780638e539e8c1461047d57806391ddadf41461049057806395d89b41146104af5780639711715a146104b757600080fd5b8063715018a61461041b57806379cc6790146104235780637ecebe00146104365780638456cb591461044957806384b0196e1461045157600080fd5b806342966c68116101c95780635c975abb1161018d5780635c975abb146103925780635cffe9de146103a4578063613255ab146103b75780636fcfff45146103ca57806370a08231146103f257600080fd5b806342966c681461030d5780634bf5d7e9146103205780634ee2cd7e14610328578063587cde1e1461033b5780635c19a95c1461037f57600080fd5b80633644e515116102105780633644e515146102c257806339509351146102ca5780633a46b1a8146102dd5780633f4ba83a146102f057806340c10f19146102fa57600080fd5b806306fdde031461024d578063095ea7b31461026b57806318160ddd1461028e57806323b872dd146102a0578063313ce567146102b3575b600080fd5b6102556105a7565b6040516102629190612a09565b60405180910390f35b61027e610279366004612a31565b610639565b6040519015158152602001610262565b6002545b604051908152602001610262565b61027e6102ae366004612a5d565b610653565b60405160128152602001610262565b610292610677565b61027e6102d8366004612a31565b610686565b6102926102eb366004612a31565b6106a8565b6102f8610732565b005b6102f8610308366004612a31565b610744565b6102f861031b366004612a9e565b61075a565b610255610767565b610292610336366004612a31565b6107ff565b610367610349366004612ab7565b6001600160a01b039081166000908152600e60205260409020541690565b6040516001600160a01b039091168152602001610262565b6102f861038d366004612ab7565b610858565b600954600160a01b900460ff1661027e565b61027e6103b2366004612ad4565b610862565b6102926103c5366004612ab7565b610a55565b6103dd6103d8366004612ab7565b610a7d565b60405163ffffffff9091168152602001610262565b610292610400366004612ab7565b6001600160a01b031660009081526020819052604090205490565b6102f8610a9f565b6102f8610431366004612a31565b610ab1565b610292610444366004612ab7565b610ac6565b6102f8610ae4565b610459610af4565b6040516102629796959493929190612b73565b6009546001600160a01b0316610367565b61029261048b366004612a9e565b610b7d565b610498610be4565b60405165ffffffffffff9091168152602001610262565b610255610bef565b6102f8610bfe565b6102926104cd366004612a9e565b610c0e565b6102926104e0366004612ab7565b610c39565b61027e6104f3366004612a31565b610cbb565b61027e610506366004612a31565b610d36565b6102f8610519366004612c1a565b610d44565b6102f861052c366004612c74565b610e7a565b61029261053f366004612a31565b610fde565b610292610552366004612ce2565b61103f565b61056a610565366004612d1b565b61106a565b60408051825163ffffffff1681526020928301516001600160e01b03169281019290925201610262565b6102f86105a2366004612ab7565b6110ee565b6060600380546105b690612d52565b80601f01602080910402602001604051908101604052809291908181526020018280546105e290612d52565b801561062f5780601f106106045761010080835404028352916020019161062f565b820191906000526020600020905b81548152906001019060200180831161061257829003601f168201915b5050505050905090565b6000336106478185856114d5565b60019150505b92915050565b6000336106618582856115f9565b61066c85858561166d565b506001949350505050565b6000610681611822565b905090565b600033610647818585610699838361103f565b6106a39190612d9d565b6114d5565b60006106b2610be4565b65ffffffffffff1682106107095760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b60448201526064015b60405180910390fd5b6001600160a01b0383166000908152600f6020526040902061072b908361194d565b9392505050565b61073a611a36565b610742611a90565b565b61074c611a36565b6107568282611ae5565b5050565b6107643382611aef565b50565b606043610772610be4565b65ffffffffffff16146107c75760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a2062726f6b656e20636c6f636b206d6f64650000006044820152606401610700565b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b6001600160a01b038216600090815260056020526040812081908190610826908590611af9565b915091508161084d576001600160a01b03851660009081526020819052604090205461084f565b805b95945050505050565b6107643382611bf0565b600061086d85610a55565b8411156108d05760405162461bcd60e51b815260206004820152602b60248201527f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60448201526a30bc233630b9b42637b0b760a91b6064820152608401610700565b60006108dc8686610fde565b90506108e88786611ae5565b6040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038916906323e30c8b906109409033908b908b9088908c908c90600401612db5565b602060405180830381600087803b15801561095a57600080fd5b505af115801561096e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109929190612e11565b146109eb5760405162461bcd60e51b8152602060048201526024808201527f4552433230466c6173684d696e743a20696e76616c69642072657475726e2076604482015263616c756560e01b6064820152608401610700565b6000610a0188306109fc858a612d9d565b6115f9565b811580610a1557506001600160a01b038116155b15610a3257610a2d88610a288489612d9d565b611aef565b610a47565b610a3c8887611aef565b610a4788828461166d565b506001979650505050505050565b60006001600160a01b0382163014610a6e57600061064d565b60025461064d90600019612e2a565b6001600160a01b0381166000908152600f602052604081205461064d9061137a565b610aa7611a36565b6107426000611c69565b610abc8233836115f9565b6107568282611aef565b6001600160a01b0381166000908152600c602052604081205461064d565b610aec611a36565b610742611cbb565b600060608082808083610b287f54484520454e44204953204e454152000000000000000000000000000000000f600a611cfe565b610b537f3100000000000000000000000000000000000000000000000000000000000001600b611cfe565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6000610b87610be4565b65ffffffffffff168210610bd95760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b6044820152606401610700565b61064d60108361194d565b60006106814361145e565b6060600480546105b690612d52565b610c06611a36565b610764611da2565b6000806000610c1e846006611af9565b9150915081610c2f57600254610c31565b805b949350505050565b6001600160a01b0381166000908152600f60205260408120548015610ca8576001600160a01b0383166000908152600f6020526040902080546000198301908110610c8657610c86612e41565b60009182526020909120015464010000000090046001600160e01b0316610cab565b60005b6001600160e01b03169392505050565b60003381610cc9828661103f565b905083811015610d295760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610700565b61066c82868684036114d5565b60003361064781858561166d565b83421115610d945760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a207369676e617475726520657870697265640000006044820152606401610700565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090610e0e90610e069060a00160405160208183030381529060405280519060200120611dfc565b858585611e29565b9050610e1981611e51565b8614610e675760405162461bcd60e51b815260206004820152601960248201527f4552433230566f7465733a20696e76616c6964206e6f6e6365000000000000006044820152606401610700565b610e718188611bf0565b50505050505050565b83421115610eca5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610700565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610ef98c611e51565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610f5482611dfc565b90506000610f6482878787611e29565b9050896001600160a01b0316816001600160a01b031614610fc75760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610700565b610fd28a8a8a6114d5565b50505050505050505050565b60006001600160a01b03831630146110385760405162461bcd60e51b815260206004820152601b60248201527f4552433230466c6173684d696e743a2077726f6e6720746f6b656e00000000006044820152606401610700565b600061072b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60408051808201909152600080825260208201526001600160a01b0383166000908152600f60205260409020805463ffffffff84169081106110ae576110ae612e41565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160e01b0316918101919091529392505050565b6110f6611a36565b6001600160a01b03811661115b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610700565b61076481611c69565b60006020835110156111805761117983611e79565b905061064d565b82828151611191926020019061292c565b5060ff905061064d565b90565b6111a8828261122e565b6002546001600160e01b03101561121a5760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b6064820152608401610700565b611228601061130183611eb7565b50505050565b6001600160a01b0382166112845760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610700565b6112906000838361202c565b80600260008282546112a29190612d9d565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36107566000838361203f565b600061072b8284612d9d565b60006001600160e01b038211156113765760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610700565b5090565b600063ffffffff8211156113765760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610700565b6001600160a01b038316611403576113f68261204a565b6113fe61207c565b505050565b6001600160a01b03821661141a576113f68361204a565b6114238361204a565b6113fe8261204a565b6001600160a01b038381166000908152600e60205260408082205485841683529120546113fe9291821691168361208a565b600065ffffffffffff8211156113765760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610700565b600061072b8284612e2a565b5490565b6001600160a01b0383166115375760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610700565b6001600160a01b0382166115985760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610700565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000611605848461103f565b9050600019811461122857818110156116605760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610700565b61122884848484036114d5565b6001600160a01b0383166116d15760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610700565b6001600160a01b0382166117335760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610700565b61173e83838361202c565b6001600160a01b038316600090815260208190526040902054818110156117b65760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610700565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361122884848461203f565b6000306001600160a01b037f00000000000000000000000075346606bed690891b3888725488b81a71e526d71614801561187b57507f000000000000000000000000000000000000000000000000000000000000000146145b156118a557507fab5f0e77b01c0d119cbd86611998976b1df53c832c91abba2420b7b4d466ff4390565b610681604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fcde00ad0c13fd20a6958aca0d52fe9756e408c136c4671749aa2a47737fd1444918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b8154600090818160058111156119a7576000611968846121c7565b6119729085612e2a565b600088815260209020909150869082015463ffffffff161115611997578091506119a5565b6119a2816001612d9d565b92505b505b808210156119f45760006119bb83836122ac565b600088815260209020909150869082015463ffffffff1611156119e0578091506119ee565b6119eb816001612d9d565b92505b506119a7565b8015611a20576000868152602090208101600019015464010000000090046001600160e01b0316611a23565b60005b6001600160e01b03169695505050505050565b6009546001600160a01b031633146107425760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610700565b611a986122c7565b6009805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b610756828261119e565b6107568282612317565b60008060008411611b455760405162461bcd60e51b815260206004820152601660248201527504552433230536e617073686f743a20696420697320360541b6044820152606401610700565b611b4d61232f565b841115611b9c5760405162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e742069640000006044820152606401610700565b6000611ba8848661233a565b8454909150811415611bc1576000809250925050611be9565b6001846001018281548110611bd857611bd8612e41565b906000526020600020015492509250505b9250929050565b6001600160a01b038281166000818152600e60208181526040808420805485845282862054949093528787166001600160a01b03198416811790915590519190951694919391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a461122882848361208a565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611cc36123e5565b6009805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611ac83390565b606060ff8314611d115761117983612432565b818054611d1d90612d52565b80601f0160208091040260200160405190810160405280929190818152602001828054611d4990612d52565b8015611d965780601f10611d6b57610100808354040283529160200191611d96565b820191906000526020600020905b815481529060010190602001808311611d7957829003601f168201915b5050505050905061064d565b6000611db2600880546001019055565b6000611dbc61232f565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb6781604051611def91815260200190565b60405180910390a1919050565b600061064d611e09611822565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000611e3a87878787612471565b91509150611e4781612535565b5095945050505050565b6001600160a01b0381166000908152600c602052604090208054600181018255905b50919050565b600080829050601f81511115611ea4578260405163305a27a960e01b81526004016107009190612a09565b8051611eaf82612e57565b179392505050565b82546000908190818115611f045760008781526020902082016000190160408051808201909152905463ffffffff8116825264010000000090046001600160e01b03166020820152611f19565b60408051808201909152600080825260208201525b905080602001516001600160e01b03169350611f3984868863ffffffff16565b9250600082118015611f635750611f4e610be4565b65ffffffffffff16816000015163ffffffff16145b15611fa857611f718361130d565b60008881526020902083016000190180546001600160e01b03929092166401000000000263ffffffff909216919091179055612022565b866040518060400160405280611fcc611fbf610be4565b65ffffffffffff1661137a565b63ffffffff168152602001611fe08661130d565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b5050935093915050565b6120346123e5565b6113fe8383836113df565b6113fe83838361142c565b6001600160a01b038116600090815260056020908152604080832091839052909120546107649190612683565b612683565b610742600661207760025490565b816001600160a01b0316836001600160a01b0316141580156120ac5750600081115b156113fe576001600160a01b0383161561213a576001600160a01b0383166000908152600f6020526040812081906120e7906114c585611eb7565b91509150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405161212f929190918252602082015260400190565b60405180910390a250505b6001600160a01b038216156113fe576001600160a01b0382166000908152600f6020526040812081906121709061130185611eb7565b91509150836001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516121b8929190918252602082015260400190565b60405180910390a25050505050565b6000816121d657506000919050565b600060016121e3846126cd565b901c6001901b905060018184816121fc576121fc612e7b565b048201901c9050600181848161221457612214612e7b565b048201901c9050600181848161222c5761222c612e7b565b048201901c9050600181848161224457612244612e7b565b048201901c9050600181848161225c5761225c612e7b565b048201901c9050600181848161227457612274612e7b565b048201901c9050600181848161228c5761228c612e7b565b048201901c905061072b818285816122a6576122a6612e7b565b04612761565b60006122bb6002848418612e91565b61072b90848416612d9d565b600954600160a01b900460ff166107425760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610700565b6123218282612777565b61122860106114c583611eb7565b600061068160085490565b815460009061234b5750600061064d565b82546000905b8082101561239857600061236583836122ac565b6000878152602090209091508590820154111561238457809150612392565b61238f816001612d9d565b92505b50612351565b6000821180156123c45750836123c1866123b3600186612e2a565b600091825260209091200190565b54145b156123dd576123d4600183612e2a565b9250505061064d565b50905061064d565b600954600160a01b900460ff16156107425760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610700565b6060600061243f836128bc565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156124a8575060009050600361252c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156124fc573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166125255760006001925092505061252c565b9150600090505b94509492505050565b600081600481111561254957612549612eb3565b14156125525750565b600181600481111561256657612566612eb3565b14156125b45760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610700565b60028160048111156125c8576125c8612eb3565b14156126165760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610700565b600381600481111561262a5761262a612eb3565b14156107645760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610700565b600061268d61232f565b905080612699846128e4565b10156113fe578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b600080608083901c156126e257608092831c92015b604083901c156126f457604092831c92015b602083901c1561270657602092831c92015b601083901c1561271857601092831c92015b600883901c1561272a57600892831c92015b600483901c1561273c57600492831c92015b600283901c1561274e57600292831c92015b600183901c1561064d5760010192915050565b6000818310612770578161072b565b5090919050565b6001600160a01b0382166127d75760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610700565b6127e38260008361202c565b6001600160a01b038216600090815260208190526040902054818110156128575760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610700565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36113fe8360008461203f565b600060ff8216601f81111561064d57604051632cd44ac360e21b815260040160405180910390fd5b80546000906128f557506000919050565b8154829061290590600190612e2a565b8154811061291557612915612e41565b90600052602060002001549050919050565b919050565b82805461293890612d52565b90600052602060002090601f01602090048101928261295a57600085556129a0565b82601f1061297357805160ff19168380011785556129a0565b828001600101855582156129a0579182015b828111156129a0578251825591602001919060010190612985565b506113769291505b8082111561137657600081556001016129a8565b6000815180845260005b818110156129e2576020818501810151868301820152016129c6565b818111156129f4576000602083870101525b50601f01601f19169290920160200192915050565b60208152600061072b60208301846129bc565b6001600160a01b038116811461076457600080fd5b60008060408385031215612a4457600080fd5b8235612a4f81612a1c565b946020939093013593505050565b600080600060608486031215612a7257600080fd5b8335612a7d81612a1c565b92506020840135612a8d81612a1c565b929592945050506040919091013590565b600060208284031215612ab057600080fd5b5035919050565b600060208284031215612ac957600080fd5b813561072b81612a1c565b600080600080600060808688031215612aec57600080fd5b8535612af781612a1c565b94506020860135612b0781612a1c565b935060408601359250606086013567ffffffffffffffff80821115612b2b57600080fd5b818801915088601f830112612b3f57600080fd5b813581811115612b4e57600080fd5b896020828501011115612b6057600080fd5b9699959850939650602001949392505050565b60ff60f81b881681526000602060e081840152612b9360e084018a6129bc565b8381036040850152612ba5818a6129bc565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015612bf757835183529284019291840191600101612bdb565b50909c9b505050505050505050505050565b803560ff8116811461292757600080fd5b60008060008060008060c08789031215612c3357600080fd5b8635612c3e81612a1c565b95506020870135945060408701359350612c5a60608801612c09565b92506080870135915060a087013590509295509295509295565b600080600080600080600060e0888a031215612c8f57600080fd5b8735612c9a81612a1c565b96506020880135612caa81612a1c565b95506040880135945060608801359350612cc660808901612c09565b925060a0880135915060c0880135905092959891949750929550565b60008060408385031215612cf557600080fd5b8235612d0081612a1c565b91506020830135612d1081612a1c565b809150509250929050565b60008060408385031215612d2e57600080fd5b8235612d3981612a1c565b9150602083013563ffffffff81168114612d1057600080fd5b600181811c90821680612d6657607f821691505b60208210811415611e7357634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612db057612db0612d87565b500190565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c0840137600060c0848401015260c0601f19601f8501168301019050979650505050505050565b600060208284031215612e2357600080fd5b5051919050565b600082821015612e3c57612e3c612d87565b500390565b634e487b7160e01b600052603260045260246000fd5b80516020808301519190811015611e735760001960209190910360031b1b16919050565b634e487b7160e01b600052601260045260246000fd5b600082612eae57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220f22a03b5546797be6c1f2571a39a330ebdbf825b68d5917697b2972e0fc9ae5764736f6c63430008090033

Deployed Bytecode Sourcemap

144200:1434:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103734:100;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;106094:201;;;;;;:::i;:::-;;:::i;:::-;;;1337:14:1;;1330:22;1312:41;;1300:2;1285:18;106094:201:0;1172:187:1;104863:108:0;104951:12;;104863:108;;;1510:25:1;;;1498:2;1483:18;104863:108:0;1364:177:1;106875:261:0;;;;;;:::i;:::-;;:::i;104705:93::-;;;104788:2;2149:36:1;;2137:2;2122:18;104705:93:0;2007:184:1;122354:115:0;;;:::i;107545:238::-;;;;;;:::i;:::-;;:::i;126232:251::-;;;;;;:::i;:::-;;:::i;144647:65::-;;;:::i;:::-;;144720:95;;;;;;:::i;:::-;;:::i;143538:91::-;;;;;;:::i;:::-;;:::i;124769:258::-;;;:::i;139088:266::-;;;;;;:::i;:::-;;:::i;125583:128::-;;;;;;:::i;:::-;-1:-1:-1;;;;;125684:19:0;;;125657:7;125684:19;;;:10;:19;;;;;;;;125583:128;;;;-1:-1:-1;;;;;2979:32:1;;;2961:51;;2949:2;2934:18;125583:128:0;2815:203:1;129106:114:0;;;;;;:::i;:::-;;:::i;94307:86::-;94378:7;;-1:-1:-1;;;94378:7:0;;;;94307:86;;118575:959;;;;;;:::i;:::-;;:::i;115661:178::-;;;;;;:::i;:::-;;:::i;125339:151::-;;;;;;:::i;:::-;;:::i;:::-;;;4166:10:1;4154:23;;;4136:42;;4124:2;4109:18;125339:151:0;3992:192:1;105034:127:0;;;;;;:::i;:::-;-1:-1:-1;;;;;105135:18:0;105108:7;105135:18;;;;;;;;;;;;105034:127;97171:103;;;:::i;143948:164::-;;;;;;:::i;:::-;;:::i;122096:128::-;;;;;;:::i;:::-;;:::i;144578:61::-;;;:::i;87011:657::-;;;:::i;:::-;;;;;;;;;;;;;:::i;96530:87::-;96603:6;;-1:-1:-1;;;;;96603:6:0;96530:87;;126755:242;;;;;;:::i;:::-;;:::i;124531:120::-;;;:::i;:::-;;;5627:14:1;5615:27;;;5597:46;;5585:2;5570:18;124531:120:0;5453:196:1;103953:104:0;;;:::i;144503:67::-;;;:::i;139458:234::-;;;;;;:::i;:::-;;:::i;125795:248::-;;;;;;:::i;:::-;;:::i;108286:436::-;;;;;;:::i;:::-;;:::i;105367:193::-;;;;;;:::i;:::-;;:::i;129302:591::-;;;;;;:::i;:::-;;:::i;121385:645::-;;;;;;:::i;:::-;;:::i;116215:219::-;;;;;;:::i;:::-;;:::i;105623:151::-;;;;;;:::i;:::-;;:::i;125109:150::-;;;;;;:::i;:::-;;:::i;:::-;;;;8192:13:1;;8207:10;8188:30;8170:49;;8279:4;8267:17;;;8261:24;-1:-1:-1;;;;;8257:50:1;8235:20;;;8228:80;;;;8143:18;125109:150:0;7968:346:1;97429:201:0;;;;;;:::i;:::-;;:::i;103734:100::-;103788:13;103821:5;103814:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103734:100;:::o;106094:201::-;106177:4;92494:10;106233:32;92494:10;106249:7;106258:6;106233:8;:32::i;:::-;106283:4;106276:11;;;106094:201;;;;;:::o;106875:261::-;106972:4;92494:10;107030:38;107046:4;92494:10;107061:6;107030:15;:38::i;:::-;107079:27;107089:4;107095:2;107099:6;107079:9;:27::i;:::-;-1:-1:-1;107124:4:0;;106875:261;-1:-1:-1;;;;106875:261:0:o;122354:115::-;122414:7;122441:20;:18;:20::i;:::-;122434:27;;122354:115;:::o;107545:238::-;107633:4;92494:10;107689:64;92494:10;107705:7;107742:10;107714:25;92494:10;107705:7;107714:9;:25::i;:::-;:38;;;;:::i;:::-;107689:8;:64::i;126232:251::-;126328:7;126368;:5;:7::i;:::-;126356:19;;:9;:19;126348:57;;;;-1:-1:-1;;;126348:57:0;;9171:2:1;126348:57:0;;;9153:21:1;9210:2;9190:18;;;9183:30;-1:-1:-1;;;9229:18:1;;;9222:55;9294:18;;126348:57:0;;;;;;;;;-1:-1:-1;;;;;126442:21:0;;;;;;:12;:21;;;;;126423:52;;126465:9;126423:18;:52::i;:::-;126416:59;126232:251;-1:-1:-1;;;126232:251:0:o;144647:65::-;96416:13;:11;:13::i;:::-;144694:10:::1;:8;:10::i;:::-;144647:65::o:0;144720:95::-;96416:13;:11;:13::i;:::-;144790:17:::1;144796:2;144800:6;144790:5;:17::i;:::-;144720:95:::0;;:::o;143538:91::-;143594:27;92494:10;143614:6;143594:5;:27::i;:::-;143538:91;:::o;124769:258::-;124829:13;124924:12;124913:7;:5;:7::i;:::-;:23;;;124905:65;;;;-1:-1:-1;;;124905:65:0;;9525:2:1;124905:65:0;;;9507:21:1;9564:2;9544:18;;;9537:30;9603:31;9583:18;;;9576:59;9652:18;;124905:65:0;9323:353:1;124905:65:0;-1:-1:-1;124981:38:0;;;;;;;;;;;;;;;;;;124769:258::o;139088:266::-;-1:-1:-1;;;;;139252:33:0;;139175:7;139252:33;;;:24;:33;;;;;139175:7;;;;139231:55;;139240:10;;139231:8;:55::i;:::-;139195:91;;;;139306:11;:40;;-1:-1:-1;;;;;105135:18:0;;105108:7;105135:18;;;;;;;;;;;139306:40;;;139320:5;139306:40;139299:47;139088:266;-1:-1:-1;;;;;139088:266:0:o;129106:114::-;129178:34;92494:10;129202:9;129178;:34::i;118575:959::-;118754:4;118789:19;118802:5;118789:12;:19::i;:::-;118779:6;:29;;118771:85;;;;-1:-1:-1;;;118771:85:0;;9883:2:1;118771:85:0;;;9865:21:1;9922:2;9902:18;;;9895:30;9961:34;9941:18;;;9934:62;-1:-1:-1;;;10012:18:1;;;10005:41;10063:19;;118771:85:0;9681:407:1;118771:85:0;118867:11;118881:23;118890:5;118897:6;118881:8;:23::i;:::-;118867:37;;118915:32;118929:8;118940:6;118915:5;:32::i;:::-;118980:58;;-1:-1:-1;;;118980:58:0;;115398:45;;-1:-1:-1;;;;;118980:20:0;;;;;:58;;119001:10;;119013:5;;119020:6;;119028:3;;119033:4;;;;118980:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:75;118958:161;;;;-1:-1:-1;;;118958:161:0;;11223:2:1;118958:161:0;;;11205:21:1;11262:2;11242:18;;;11235:30;11301:34;11281:18;;;11274:62;-1:-1:-1;;;11352:18:1;;;11345:34;11396:19;;118958:161:0;11021:400:1;118958:161:0;119130:24;119187:63;119211:8;119230:4;119237:12;119246:3;119237:6;:12;:::i;:::-;119187:15;:63::i;:::-;119265:8;;;:42;;-1:-1:-1;;;;;;119277:30:0;;;119265:42;119261:244;;;119324:38;119338:8;119349:12;119358:3;119349:6;:12;:::i;:::-;119324:5;:38::i;:::-;119261:244;;;119395:32;119409:8;119420:6;119395:5;:32::i;:::-;119442:51;119460:8;119471:16;119489:3;119442:9;:51::i;:::-;-1:-1:-1;119522:4:0;;118575:959;-1:-1:-1;;;;;;;118575:959:0:o;115661:178::-;115736:7;-1:-1:-1;;;;;115763:22:0;;115780:4;115763:22;:68;;115830:1;115763:68;;;104951:12;;115788:39;;-1:-1:-1;;115788:39:0;:::i;125339:151::-;-1:-1:-1;;;;;125453:21:0;;125409:6;125453:21;;;:12;:21;;;;;:28;125435:47;;:17;:47::i;97171:103::-;96416:13;:11;:13::i;:::-;97236:30:::1;97263:1;97236:18;:30::i;143948:164::-:0;144025:46;144041:7;92494:10;144064:6;144025:15;:46::i;:::-;144082:22;144088:7;144097:6;144082:5;:22::i;122096:128::-;-1:-1:-1;;;;;122192:14:0;;122165:7;122192:14;;;:7;:14;;;;;47370;122192:24;47278:114;144578:61;96416:13;:11;:13::i;:::-;144623:8:::1;:6;:8::i;87011:657::-:0;87132:13;87160:18;;87132:13;;;87160:18;87434:41;:5;87461:13;87434:26;:41::i;:::-;87490:47;:8;87520:16;87490:29;:47::i;:::-;87633:16;;;87616:1;87633:16;;;;;;;;;-1:-1:-1;;;87381:279:0;;;-1:-1:-1;87381:279:0;;-1:-1:-1;87552:13:0;;-1:-1:-1;87588:4:0;;-1:-1:-1;87616:1:0;-1:-1:-1;87633:16:0;-1:-1:-1;87381:279:0;-1:-1:-1;87011:657:0:o;126755:242::-;126840:7;126880;:5;:7::i;:::-;126868:19;;:9;:19;126860:57;;;;-1:-1:-1;;;126860:57:0;;9171:2:1;126860:57:0;;;9153:21:1;9210:2;9190:18;;;9183:30;-1:-1:-1;;;9229:18:1;;;9222:55;9294:18;;126860:57:0;8969:349:1;126860:57:0;126935:54;126954:23;126979:9;126935:18;:54::i;124531:120::-;124586:6;124612:31;124630:12;124612:17;:31::i;103953:104::-;104009:13;104042:7;104035:14;;;;;:::i;144503:67::-;96416:13;:11;:13::i;:::-;144551:11:::1;:9;:11::i;139458:234::-:0;139530:7;139551:16;139569:13;139586:43;139595:10;139607:21;139586:8;:43::i;:::-;139550:79;;;;139649:11;:35;;104951:12;;139649:35;;;139663:5;139649:35;139642:42;139458:234;-1:-1:-1;;;;139458:234:0:o;125795:248::-;-1:-1:-1;;;;;125902:21:0;;125868:7;125902:21;;;:12;:21;;;;;:28;125973:8;;:51;;-1:-1:-1;;;;;125988:21:0;;;;;;:12;:21;;;;;:30;;-1:-1:-1;;126010:7:0;;;125988:30;;;;;;:::i;:::-;;;;;;;;;;:36;;;;-1:-1:-1;;;;;125988:36:0;125973:51;;;125984:1;125973:51;-1:-1:-1;;;;;125966:58:0;;125795:248;-1:-1:-1;;;125795:248:0:o;108286:436::-;108379:4;92494:10;108379:4;108462:25;92494:10;108479:7;108462:9;:25::i;:::-;108435:52;;108526:15;108506:16;:35;;108498:85;;;;-1:-1:-1;;;108498:85:0;;12022:2:1;108498:85:0;;;12004:21:1;12061:2;12041:18;;;12034:30;12100:34;12080:18;;;12073:62;-1:-1:-1;;;12151:18:1;;;12144:35;12196:19;;108498:85:0;11820:401:1;108498:85:0;108619:60;108628:5;108635:7;108663:15;108644:16;:34;108619:8;:60::i;105367:193::-;105446:4;92494:10;105502:28;92494:10;105519:2;105523:6;105502:9;:28::i;129302:591::-;129529:6;129510:15;:25;;129502:67;;;;-1:-1:-1;;;129502:67:0;;12428:2:1;129502:67:0;;;12410:21:1;12467:2;12447:18;;;12440:30;12506:31;12486:18;;;12479:59;12555:18;;129502:67:0;12226:353:1;129502:67:0;129652:58;;;124144:71;129652:58;;;12815:25:1;-1:-1:-1;;;;;12876:32:1;;12856:18;;;12849:60;;;;12925:18;;;12918:34;;;12968:18;;;12961:34;;;129580:14:0;;129597:174;;129625:87;;12787:19:1;;129652:58:0;;;;;;;;;;;;129642:69;;;;;;129625:16;:87::i;:::-;129727:1;129743;129759;129597:13;:174::i;:::-;129580:191;;129799:17;129809:6;129799:9;:17::i;:::-;129790:5;:26;129782:64;;;;-1:-1:-1;;;129782:64:0;;13208:2:1;129782:64:0;;;13190:21:1;13247:2;13227:18;;;13220:30;13286:27;13266:18;;;13259:55;13331:18;;129782:64:0;13006:349:1;129782:64:0;129857:28;129867:6;129875:9;129857;:28::i;:::-;129491:402;129302:591;;;;;;:::o;121385:645::-;121629:8;121610:15;:27;;121602:69;;;;-1:-1:-1;;;121602:69:0;;13562:2:1;121602:69:0;;;13544:21:1;13601:2;13581:18;;;13574:30;13640:31;13620:18;;;13613:59;13689:18;;121602:69:0;13360:353:1;121602:69:0;121684:18;120560:95;121744:5;121751:7;121760:5;121767:16;121777:5;121767:9;:16::i;:::-;121715:79;;;;;;14005:25:1;;;;-1:-1:-1;;;;;14104:15:1;;;14084:18;;;14077:43;14156:15;;;;14136:18;;;14129:43;14188:18;;;14181:34;14231:19;;;14224:35;14275:19;;;14268:35;;;13977:19;;121715:79:0;;;;;;;;;;;;121705:90;;;;;;121684:111;;121808:12;121823:28;121840:10;121823:16;:28::i;:::-;121808:43;;121864:14;121881:28;121895:4;121901:1;121904;121907;121881:13;:28::i;:::-;121864:45;;121938:5;-1:-1:-1;;;;;121928:15:0;:6;-1:-1:-1;;;;;121928:15:0;;121920:58;;;;-1:-1:-1;;;121920:58:0;;14516:2:1;121920:58:0;;;14498:21:1;14555:2;14535:18;;;14528:30;14594:32;14574:18;;;14567:60;14644:18;;121920:58:0;14314:354:1;121920:58:0;121991:31;122000:5;122007:7;122016:5;121991:8;:31::i;:::-;121591:439;;;121385:645;;;;;;;:::o;116215:219::-;116302:7;-1:-1:-1;;;;;116330:22:0;;116347:4;116330:22;116322:62;;;;-1:-1:-1;;;116322:62:0;;14875:2:1;116322:62:0;;;14857:21:1;14914:2;14894:18;;;14887:30;14953:29;14933:18;;;14926:57;15000:18;;116322:62:0;14673:351:1;116322:62:0;116914:7;116402:24;116833:234;105623:151;-1:-1:-1;;;;;105739:18:0;;;105712:7;105739:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;105623:151::o;125109:150::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;125225:21:0;;;;;;:12;:21;;;;;:26;;;;;;;;;;;;:::i;:::-;;;;;;;;;;125218:33;;;;;;;;;125225:26;;125218:33;;;;;;;;;-1:-1:-1;;;;;125218:33:0;;;;;;;;;125109:150;-1:-1:-1;;;125109:150:0:o;97429:201::-;96416:13;:11;:13::i;:::-;-1:-1:-1;;;;;97518:22:0;::::1;97510:73;;;::::0;-1:-1:-1;;;97510:73:0;;15231:2:1;97510:73:0::1;::::0;::::1;15213:21:1::0;15270:2;15250:18;;;15243:30;15309:34;15289:18;;;15282:62;-1:-1:-1;;;15360:18:1;;;15353:36;15406:19;;97510:73:0::1;15029:402:1::0;97510:73:0::1;97594:28;97613:8;97594:18;:28::i;80497:348::-:0;80593:11;80643:2;80627:5;80621:19;:24;80617:221;;;80669:20;80683:5;80669:13;:20::i;:::-;80662:27;;;;80617:221;80763:5;80748;80722:46;;;;;;;;:::i;:::-;-1:-1:-1;78926:66:0;;-1:-1:-1;80783:43:0;;76684:207;76863:10;76684:207::o;130199:290::-;130284:28;130296:7;130305:6;130284:11;:28::i;:::-;104951:12;;-1:-1:-1;;;;;;130331:29:0;130323:90;;;;-1:-1:-1;;;130323:90:0;;15638:2:1;130323:90:0;;;15620:21:1;15677:2;15657:18;;;15650:30;15716:34;15696:18;;;15689:62;-1:-1:-1;;;15767:18:1;;;15760:46;15823:19;;130323:90:0;15436:412:1;130323:90:0;130426:55;130443:23;130468:4;130474:6;130426:16;:55::i;:::-;;;130199:290;;:::o;110285:548::-;-1:-1:-1;;;;;110369:21:0;;110361:65;;;;-1:-1:-1;;;110361:65:0;;16055:2:1;110361:65:0;;;16037:21:1;16094:2;16074:18;;;16067:30;16133:33;16113:18;;;16106:61;16184:18;;110361:65:0;15853:355:1;110361:65:0;110439:49;110468:1;110472:7;110481:6;110439:20;:49::i;:::-;110517:6;110501:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;110672:18:0;;:9;:18;;;;;;;;;;;:28;;;;;;110727:37;1510:25:1;;;110727:37:0;;1483:18:1;110727:37:0;;;;;;;110777:48;110805:1;110809:7;110818:6;110777:19;:48::i;133138:98::-;133196:7;133223:5;133227:1;133223;:5;:::i;5452:195::-;5509:7;-1:-1:-1;;;;;5537:26:0;;;5529:78;;;;-1:-1:-1;;;5529:78:0;;16415:2:1;5529:78:0;;;16397:21:1;16454:2;16434:18;;;16427:30;16493:34;16473:18;;;16466:62;-1:-1:-1;;;16544:18:1;;;16537:37;16591:19;;5529:78:0;16213:403:1;5529:78:0;-1:-1:-1;5633:5:0;5452:195::o;18288:190::-;18344:6;18380:16;18371:25;;;18363:76;;;;-1:-1:-1;;;18363:76:0;;16823:2:1;18363:76:0;;;16805:21:1;16862:2;16842:18;;;16835:30;16901:34;16881:18;;;16874:62;-1:-1:-1;;;16952:18:1;;;16945:36;16998:19;;18363:76:0;16621:402:1;139909:588:0;-1:-1:-1;;;;;140079:18:0;;140075:415;;140135:26;140158:2;140135:22;:26::i;:::-;140176:28;:26;:28::i;:::-;139909:588;;;:::o;140075:415::-;-1:-1:-1;;;;;140226:16:0;;140222:268;;140280:28;140303:4;140280:22;:28::i;140222:268::-;140409:28;140432:4;140409:22;:28::i;:::-;140452:26;140475:2;140452:22;:26::i;130924:228::-;-1:-1:-1;;;;;125684:19:0;;;125657:7;125684:19;;;:10;:19;;;;;;;;;;;;;;;131088:56;;125684:19;;;;;131137:6;131088:16;:56::i;17230:190::-;17286:6;17322:16;17313:25;;;17305:76;;;;-1:-1:-1;;;17305:76:0;;17230:2:1;17305:76:0;;;17212:21:1;17269:2;17249:18;;;17242:30;17308:34;17288:18;;;17281:62;-1:-1:-1;;;17359:18:1;;;17352:36;17405:19;;17305:76:0;17028:402:1;133244:103:0;133307:7;133334:5;133338:1;133334;:5;:::i;47278:114::-;47370:14;;47278:114::o;112279:346::-;-1:-1:-1;;;;;112381:19:0;;112373:68;;;;-1:-1:-1;;;112373:68:0;;17637:2:1;112373:68:0;;;17619:21:1;17676:2;17656:18;;;17649:30;17715:34;17695:18;;;17688:62;-1:-1:-1;;;17766:18:1;;;17759:34;17810:19;;112373:68:0;17435:400:1;112373:68:0;-1:-1:-1;;;;;112460:21:0;;112452:68;;;;-1:-1:-1;;;112452:68:0;;18042:2:1;112452:68:0;;;18024:21:1;18081:2;18061:18;;;18054:30;18120:34;18100:18;;;18093:62;-1:-1:-1;;;18171:18:1;;;18164:32;18213:19;;112452:68:0;17840:398:1;112452:68:0;-1:-1:-1;;;;;112533:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;112585:32;;1510:25:1;;;112585:32:0;;1483:18:1;112585:32:0;;;;;;;112279:346;;;:::o;112916:419::-;113017:24;113044:25;113054:5;113061:7;113044:9;:25::i;:::-;113017:52;;-1:-1:-1;;113084:16:0;:37;113080:248;;113166:6;113146:16;:26;;113138:68;;;;-1:-1:-1;;;113138:68:0;;18445:2:1;113138:68:0;;;18427:21:1;18484:2;18464:18;;;18457:30;18523:31;18503:18;;;18496:59;18572:18;;113138:68:0;18243:353:1;113138:68:0;113250:51;113259:5;113266:7;113294:6;113275:16;:25;113250:8;:51::i;109192:806::-;-1:-1:-1;;;;;109289:18:0;;109281:68;;;;-1:-1:-1;;;109281:68:0;;18803:2:1;109281:68:0;;;18785:21:1;18842:2;18822:18;;;18815:30;18881:34;18861:18;;;18854:62;-1:-1:-1;;;18932:18:1;;;18925:35;18977:19;;109281:68:0;18601:401:1;109281:68:0;-1:-1:-1;;;;;109368:16:0;;109360:64;;;;-1:-1:-1;;;109360:64:0;;19209:2:1;109360:64:0;;;19191:21:1;19248:2;19228:18;;;19221:30;19287:34;19267:18;;;19260:62;-1:-1:-1;;;19338:18:1;;;19331:33;19381:19;;109360:64:0;19007:399:1;109360:64:0;109437:38;109458:4;109464:2;109468:6;109437:20;:38::i;:::-;-1:-1:-1;;;;;109510:15:0;;109488:19;109510:15;;;;;;;;;;;109544:21;;;;109536:72;;;;-1:-1:-1;;;109536:72:0;;19613:2:1;109536:72:0;;;19595:21:1;19652:2;19632:18;;;19625:30;19691:34;19671:18;;;19664:62;-1:-1:-1;;;19742:18:1;;;19735:36;19788:19;;109536:72:0;19411:402:1;109536:72:0;-1:-1:-1;;;;;109644:15:0;;;:9;:15;;;;;;;;;;;109662:20;;;109644:38;;109862:13;;;;;;;;;;:23;;;;;;109914:26;;1510:25:1;;;109862:13:0;;109914:26;;1483:18:1;109914:26:0;;;;;;;109953:37;109973:4;109979:2;109983:6;109953:19;:37::i;85649:268::-;85702:7;85734:4;-1:-1:-1;;;;;85743:11:0;85726:28;;:63;;;;;85775:14;85758:13;:31;85726:63;85722:188;;;-1:-1:-1;85813:22:0;;85649:268::o;85722:188::-;85875:23;86017:81;;;83841:95;86017:81;;;21702:25:1;86040:11:0;21743:18:1;;;21736:34;;;;86053:14:0;21786:18:1;;;21779:34;86069:13:0;21829:18:1;;;21822:34;86092:4:0;21872:19:1;;;21865:61;85980:7:0;;21674:19:1;;86017:81:0;;;;;;;;;;;;86007:92;;;;;;86000:99;;85925:182;;127086:1934;128310:12;;127183:7;;;128310:12;128408:1;128399:10;;128395:249;;;128426:11;128449:17;128459:6;128449:9;:17::i;:::-;128440:26;;:6;:26;:::i;:::-;133581:25;133643:21;;;133710:4;133697:18;;128426:40;;-1:-1:-1;128523:9:0;;133693:28;;128485:35;;;:47;128481:152;;;128560:3;128553:10;;128481:152;;;128610:7;:3;128616:1;128610:7;:::i;:::-;128604:13;;128481:152;128411:233;128395:249;128669:4;128663:3;:10;128656:249;;;128690:11;128704:23;128717:3;128722:4;128704:12;:23::i;:::-;133581:25;133643:21;;;133710:4;133697:18;;128690:37;;-1:-1:-1;128784:9:0;;133693:28;;128746:35;;;:47;128742:152;;;128821:3;128814:10;;128742:152;;;128871:7;:3;128877:1;128871:7;:::i;:::-;128865:13;;128742:152;128675:230;128656:249;;;128949:9;;:52;;133581:25;133643:21;;;133710:4;133697:18;;133693:28;;-1:-1:-1;;133693:28:0;128965:36;;;;-1:-1:-1;;;;;128965:36:0;128949:52;;;128961:1;128949:52;-1:-1:-1;;;;;128942:59:0;;127086:1934;-1:-1:-1;;;;;;127086:1934:0:o;96695:132::-;96603:6;;-1:-1:-1;;;;;96603:6:0;92494:10;96759:23;96751:68;;;;-1:-1:-1;;;96751:68:0;;20020:2:1;96751:68:0;;;20002:21:1;;;20039:18;;;20032:30;20098:34;20078:18;;;20071:62;20150:18;;96751:68:0;19818:356:1;95162:120:0;94171:16;:14;:16::i;:::-;95221:7:::1;:15:::0;;-1:-1:-1;;;;95221:15:0::1;::::0;;95252:22:::1;92494:10:::0;95261:12:::1;95252:22;::::0;-1:-1:-1;;;;;2979:32:1;;;2961:51;;2949:2;2934:18;95252:22:0::1;;;;;;;95162:120::o:0;145323:145::-;145437:23;145449:2;145453:6;145437:11;:23::i;145476:155::-;145595:28;145607:7;145616:6;145595:11;:28::i;140505:1619::-;140594:4;140600:7;140641:1;140628:10;:14;140620:49;;;;-1:-1:-1;;;140620:49:0;;20381:2:1;140620:49:0;;;20363:21:1;20420:2;20400:18;;;20393:30;-1:-1:-1;;;20439:18:1;;;20432:52;20501:18;;140620:49:0;20179:346:1;140620:49:0;140702:23;:21;:23::i;:::-;140688:10;:37;;140680:79;;;;-1:-1:-1;;;140680:79:0;;20732:2:1;140680:79:0;;;20714:21:1;20771:2;20751:18;;;20744:30;20810:31;20790:18;;;20783:59;20859:18;;140680:79:0;20530:353:1;140680:79:0;141898:13;141914:40;:9;141943:10;141914:28;:40::i;:::-;141980:20;;141898:56;;-1:-1:-1;141971:29:0;;141967:150;;;142025:5;142032:1;142017:17;;;;;;;141967:150;142075:4;142081:9;:16;;142098:5;142081:23;;;;;;;;:::i;:::-;;;;;;;;;142067:38;;;;;140505:1619;;;;;;:::o;131330:388::-;-1:-1:-1;;;;;125684:19:0;;;131415:23;125684:19;;;:10;:19;;;;;;;;;;105135:18;;;;;;;131530:21;;;;:33;;;-1:-1:-1;;;;;;131530:33:0;;;;;;;131581:54;;125684:19;;;;;105135:18;;131530:33;;125684:19;;;131581:54;;131415:23;131581:54;131648:62;131665:15;131682:9;131693:16;131648;:62::i;97790:191::-;97883:6;;;-1:-1:-1;;;;;97900:17:0;;;-1:-1:-1;;;;;;97900:17:0;;;;;;;97933:40;;97883:6;;;97900:17;97883:6;;97933:40;;97864:16;;97933:40;97853:128;97790:191;:::o;94903:118::-;93912:19;:17;:19::i;:::-;94963:7:::1;:14:::0;;-1:-1:-1;;;;94963:14:0::1;-1:-1:-1::0;;;94963:14:0::1;::::0;;94993:20:::1;95000:12;92494:10:::0;;92414:98;80981:274;81075:13;78926:66;81105:47;;81101:147;;81176:15;81185:5;81176:8;:15::i;81101:147::-;81231:5;81224:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;138560:223;138607:7;138627:30;:18;47489:19;;47507:1;47489:19;;;47400:127;138627:30;138670:17;138690:23;:21;:23::i;:::-;138670:43;;138729:19;138738:9;138729:19;;;;1510:25:1;;1498:2;1483:18;;1364:177;138729:19:0;;;;;;;;138766:9;138560:223;-1:-1:-1;138560:223:0:o;86749:167::-;86826:7;86853:55;86875:20;:18;:20::i;:::-;86897:10;72615:4;72609:11;-1:-1:-1;;;72634:23:0;;72687:4;72678:14;;72671:39;;;;72740:4;72731:14;;72724:34;72795:4;72780:20;;;72412:406;70628:236;70713:7;70734:17;70753:18;70775:25;70786:4;70792:1;70795;70798;70775:10;:25::i;:::-;70733:67;;;;70811:18;70823:5;70811:11;:18::i;:::-;-1:-1:-1;70847:9:0;70628:236;-1:-1:-1;;;;;70628:236:0:o;122607:207::-;-1:-1:-1;;;;;122728:14:0;;122667:15;122728:14;;;:7;:14;;;;;47370;;47507:1;47489:19;;;;47370:14;122789:17;122684:130;122607:207;;;:::o;79254:292::-;79319:11;79343:17;79369:3;79343:30;;79402:2;79388:4;:11;:16;79384:74;;;79442:3;79428:18;;-1:-1:-1;;;79428:18:0;;;;;;;;:::i;79384:74::-;79525:11;;79508:13;79525:4;79508:13;:::i;:::-;79500:36;;79254:292;-1:-1:-1;;;79254:292:0:o;132343:787::-;132580:12;;132517:17;;;;;132658:8;;:59;;133581:25;133643:21;;;133710:4;133697:18;;133693:28;;-1:-1:-1;;133693:28:0;132658:59;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;132658:59:0;;;;;;;;132669:16;;;;;;;;;-1:-1:-1;132669:16:0;;;;;;;132658:59;132630:87;;132746:7;:13;;;-1:-1:-1;;;;;132734:25:0;;;132786:20;132789:9;132800:5;132786:2;:20;;:::i;:::-;132774:32;;132833:1;132827:3;:7;:39;;;;;132859:7;:5;:7::i;:::-;132838:28;;:7;:17;;;:28;;;132827:39;132823:289;;;132925:29;132944:9;132925:18;:29::i;:::-;133581:25;133643:21;;;133710:4;133697:18;;133693:28;;-1:-1:-1;;133693:28:0;132887:67;;-1:-1:-1;;;;;132887:67:0;;;;;;;;;;;;;;;;132823:289;;;132995:5;133006:89;;;;;;;;133029:26;133047:7;:5;:7::i;:::-;133029:26;;:17;:26::i;:::-;133006:89;;;;;;133064:29;133083:9;133064:18;:29::i;:::-;-1:-1:-1;;;;;133006:89:0;;;;;;132995:101;;;;;;;-1:-1:-1;132995:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132823:289;132605:518;132555:575;132343:787;;;;;;:::o;144823:221::-;93912:19;:17;:19::i;:::-;144992:44:::1;145019:4;145025:2;145029:6;144992:26;:44::i;145122:193::-:0;145264:43;145290:4;145296:2;145300:6;145264:25;:43::i;142132:146::-;-1:-1:-1;;;;;142216:33:0;;;;;;:24;:33;;;;;;;;105135:18;;;;;;;;142200:70;;142216:33;142200:15;:70::i;142251:18::-;142200:15;:70::i;142286:118::-;142343:53;142359:21;142382:13;104951:12;;;104863:108;131726:609;131824:3;-1:-1:-1;;;;;131817:10:0;:3;-1:-1:-1;;;;;131817:10:0;;;:24;;;;;131840:1;131831:6;:10;131817:24;131813:515;;;-1:-1:-1;;;;;131862:17:0;;;131858:224;;-1:-1:-1;;;;;131958:17:0;;131901;131958;;;:12;:17;;;;;131901;;131941:54;;131977:9;131988:6;131941:16;:54::i;:::-;131900:95;;;;132040:3;-1:-1:-1;;;;;132019:47:0;;132045:9;132056;132019:47;;;;;;21364:25:1;;;21420:2;21405:18;;21398:34;21352:2;21337:18;;21190:248;132019:47:0;;;;;;;;131881:201;;131858:224;-1:-1:-1;;;;;132102:17:0;;;132098:219;;-1:-1:-1;;;;;132198:17:0;;132141;132198;;;:12;:17;;;;;132141;;132181:49;;132217:4;132223:6;132181:16;:49::i;:::-;132140:90;;;;132275:3;-1:-1:-1;;;;;132254:47:0;;132280:9;132291;132254:47;;;;;;21364:25:1;;;21420:2;21405:18;;21398:34;21352:2;21337:18;;21190:248;132254:47:0;;;;;;;;132121:196;;131726:609;;;:::o;54583:1673::-;54631:7;54655:6;54651:47;;-1:-1:-1;54685:1:0;;54583:1673;-1:-1:-1;54583:1673:0:o;54651:47::-;55389:14;55423:1;55412:7;55417:1;55412:4;:7::i;:::-;:12;;55406:1;:19;;55389:36;;55891:1;55880:6;55876:1;:10;;;;;:::i;:::-;;55867:6;:19;55866:26;;55857:35;;55941:1;55930:6;55926:1;:10;;;;;:::i;:::-;;55917:6;:19;55916:26;;55907:35;;55991:1;55980:6;55976:1;:10;;;;;:::i;:::-;;55967:6;:19;55966:26;;55957:35;;56041:1;56030:6;56026:1;:10;;;;;:::i;:::-;;56017:6;:19;56016:26;;56007:35;;56091:1;56080:6;56076:1;:10;;;;;:::i;:::-;;56067:6;:19;56066:26;;56057:35;;56141:1;56130:6;56126:1;:10;;;;;:::i;:::-;;56117:6;:19;56116:26;;56107:35;;56191:1;56180:6;56176:1;:10;;;;;:::i;:::-;;56167:6;:19;56166:26;;56157:35;;56214:23;56218:6;56230;56226:1;:10;;;;;:::i;:::-;;56214:3;:23::i;48740:156::-;48802:7;48877:11;48887:1;48878:5;;;48877:11;:::i;:::-;48867:21;;48868:5;;;48867:21;:::i;94651:108::-;94378:7;;-1:-1:-1;;;94378:7:0;;;;94710:41;;;;-1:-1:-1;;;94710:41:0;;22493:2:1;94710:41:0;;;22475:21:1;22532:2;22512:18;;;22505:30;-1:-1:-1;;;22551:18:1;;;22544:50;22611:18;;94710:41:0;22291:344:1;130583:194:0;130668:28;130680:7;130689:6;130668:11;:28::i;:::-;130709:60;130726:23;130751:9;130762:6;130709:16;:60::i;138849:127::-;138913:7;138940:28;:18;47370:14;;47278:114;88385:958;88498:12;;88474:7;;88494:58;;-1:-1:-1;88539:1:0;88532:8;;88494:58;88605:12;;88564:11;;88630:444;88643:4;88637:3;:10;88630:444;;;88664:11;88678:23;88691:3;88696:4;88678:12;:23::i;:::-;91219:31;91596:19;;;91654:4;91641:18;;88664:37;;-1:-1:-1;88955:7:0;;91637:28;;88922:30;:40;88918:145;;;88990:3;88983:10;;88918:145;;;89040:7;:3;89046:1;89040:7;:::i;:::-;89034:13;;88918:145;88649:425;88630:444;;;89200:1;89194:3;:7;:56;;;;-1:-1:-1;89243:7:0;89205:28;89218:5;89225:7;89231:1;89225:3;:7;:::i;:::-;91219:31;91596:19;;;91654:4;91641:18;;;91637:28;;91138:584;89205:28;:34;:45;89194:56;89190:146;;;89274:7;89280:1;89274:3;:7;:::i;:::-;89267:14;;;;;;89190:146;-1:-1:-1;89321:3:0;-1:-1:-1;89314:10:0;;94466:108;94378:7;;-1:-1:-1;;;94378:7:0;;;;94536:9;94528:38;;;;-1:-1:-1;;;94528:38:0;;22842:2:1;94528:38:0;;;22824:21:1;22881:2;22861:18;;;22854:30;-1:-1:-1;;;22900:18:1;;;22893:46;22956:18;;94528:38:0;22640:340:1;79635:415:0;79694:13;79720:11;79734:16;79745:4;79734:10;:16::i;:::-;79860:14;;;79871:2;79860:14;;;;;;;;;79720:30;;-1:-1:-1;79840:17:0;;79860:14;;;;;;;;;-1:-1:-1;;;79953:16:0;;;-1:-1:-1;79999:4:0;79990:14;;79983:28;;;;-1:-1:-1;79953:16:0;79635:415::o;69012:1477::-;69100:7;;70034:66;70021:79;;70017:163;;;-1:-1:-1;70133:1:0;;-1:-1:-1;70137:30:0;70117:51;;70017:163;70294:24;;;70277:14;70294:24;;;;;;;;;23212:25:1;;;23285:4;23273:17;;23253:18;;;23246:45;;;;23307:18;;;23300:34;;;23350:18;;;23343:34;;;70294:24:0;;23184:19:1;;70294:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;70294:24:0;;-1:-1:-1;;70294:24:0;;;-1:-1:-1;;;;;;;70333:20:0;;70329:103;;70386:1;70390:29;70370:50;;;;;;;70329:103;70452:6;-1:-1:-1;70460:20:0;;-1:-1:-1;69012:1477:0;;;;;;;;:::o;64472:521::-;64550:20;64541:5;:29;;;;;;;;:::i;:::-;;64537:449;;;64472:521;:::o;64537:449::-;64648:29;64639:5;:38;;;;;;;;:::i;:::-;;64635:351;;;64694:34;;-1:-1:-1;;;64694:34:0;;23722:2:1;64694:34:0;;;23704:21:1;23761:2;23741:18;;;23734:30;23800:26;23780:18;;;23773:54;23844:18;;64694:34:0;23520:348:1;64635:351:0;64759:35;64750:5;:44;;;;;;;;:::i;:::-;;64746:240;;;64811:41;;-1:-1:-1;;;64811:41:0;;24075:2:1;64811:41:0;;;24057:21:1;24114:2;24094:18;;;24087:30;24153:33;24133:18;;;24126:61;24204:18;;64811:41:0;23873:355:1;64746:240:0;64883:30;64874:5;:39;;;;;;;;:::i;:::-;;64870:116;;;64930:44;;-1:-1:-1;;;64930:44:0;;24435:2:1;64930:44:0;;;24417:21:1;24474:2;24454:18;;;24447:30;24513:34;24493:18;;;24486:62;-1:-1:-1;;;24564:18:1;;;24557:32;24606:19;;64930:44:0;24233:398:1;142412:310:0;142507:17;142527:23;:21;:23::i;:::-;142507:43;-1:-1:-1;142507:43:0;142565:30;142581:9;142565:15;:30::i;:::-;:42;142561:154;;;142624:29;;;;;;;;-1:-1:-1;142624:29:0;;;;;;;;;;;;;;142668:16;;;:35;;;;;;;;;;;;;;;142412:310::o;56733:1019::-;56785:7;;56872:3;56863:12;;;:16;56859:102;;56910:3;56900:13;;;;56932;56859:102;56988:2;56979:11;;;:15;56975:99;;57025:2;57015:12;;;;57046;56975:99;57101:2;57092:11;;;:15;57088:99;;57138:2;57128:12;;;;57159;57088:99;57214:2;57205:11;;;:15;57201:99;;57251:2;57241:12;;;;57272;57201:99;57327:1;57318:10;;;:14;57314:96;;57363:1;57353:11;;;;57383;57314:96;57437:1;57428:10;;;:14;57424:96;;57473:1;57463:11;;;;57493;57424:96;57547:1;57538:10;;;:14;57534:96;;57583:1;57573:11;;;;57603;57534:96;57657:1;57648:10;;;:14;57644:66;;57693:1;57683:11;57738:6;56733:1019;-1:-1:-1;;56733:1019:0:o;48515:106::-;48573:7;48604:1;48600;:5;:13;;48612:1;48600:13;;;-1:-1:-1;48608:1:0;;48515:106;-1:-1:-1;48515:106:0:o;111166:675::-;-1:-1:-1;;;;;111250:21:0;;111242:67;;;;-1:-1:-1;;;111242:67:0;;24838:2:1;111242:67:0;;;24820:21:1;24877:2;24857:18;;;24850:30;24916:34;24896:18;;;24889:62;-1:-1:-1;;;24967:18:1;;;24960:31;25008:19;;111242:67:0;24636:397:1;111242:67:0;111322:49;111343:7;111360:1;111364:6;111322:20;:49::i;:::-;-1:-1:-1;;;;;111409:18:0;;111384:22;111409:18;;;;;;;;;;;111446:24;;;;111438:71;;;;-1:-1:-1;;;111438:71:0;;25240:2:1;111438:71:0;;;25222:21:1;25279:2;25259:18;;;25252:30;25318:34;25298:18;;;25291:62;-1:-1:-1;;;25369:18:1;;;25362:32;25411:19;;111438:71:0;25038:398:1;111438:71:0;-1:-1:-1;;;;;111545:18:0;;:9;:18;;;;;;;;;;;111566:23;;;111545:44;;111684:12;:22;;;;;;;111735:37;1510:25:1;;;111545:9:0;;:18;111735:37;;1483:18:1;111735:37:0;;;;;;;111785:48;111805:7;111822:1;111826:6;111785:19;:48::i;80127:251::-;80188:7;80261:4;80225:40;;80289:2;80280:11;;80276:71;;;80315:20;;-1:-1:-1;;;80315:20:0;;;;;;;;;;;142730:212;142824:10;;142800:7;;142820:115;;-1:-1:-1;142863:1:0;;142730:212;-1:-1:-1;142730:212:0:o;142820:115::-;142908:10;;142904:3;;142908:14;;142921:1;;142908:14;:::i;:::-;142904:19;;;;;;;;:::i;:::-;;;;;;;;;142897:26;;142730:212;;;:::o;142820:115::-;142730:212;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:472:1;56:3;94:5;88:12;121:6;116:3;109:19;146:1;156:162;170:6;167:1;164:13;156:162;;;232:4;288:13;;;284:22;;278:29;260:11;;;256:20;;249:59;185:12;156:162;;;336:6;333:1;330:13;327:87;;;402:1;395:4;386:6;381:3;377:16;373:27;366:38;327:87;-1:-1:-1;468:2:1;447:15;-1:-1:-1;;443:29:1;434:39;;;;475:4;430:50;;14:472;-1:-1:-1;;14:472:1:o;491:220::-;640:2;629:9;622:21;603:4;660:45;701:2;690:9;686:18;678:6;660:45;:::i;716:131::-;-1:-1:-1;;;;;791:31:1;;781:42;;771:70;;837:1;834;827:12;852:315;920:6;928;981:2;969:9;960:7;956:23;952:32;949:52;;;997:1;994;987:12;949:52;1036:9;1023:23;1055:31;1080:5;1055:31;:::i;:::-;1105:5;1157:2;1142:18;;;;1129:32;;-1:-1:-1;;;852:315:1:o;1546:456::-;1623:6;1631;1639;1692:2;1680:9;1671:7;1667:23;1663:32;1660:52;;;1708:1;1705;1698:12;1660:52;1747:9;1734:23;1766:31;1791:5;1766:31;:::i;:::-;1816:5;-1:-1:-1;1873:2:1;1858:18;;1845:32;1886:33;1845:32;1886:33;:::i;:::-;1546:456;;1938:7;;-1:-1:-1;;;1992:2:1;1977:18;;;;1964:32;;1546:456::o;2378:180::-;2437:6;2490:2;2478:9;2469:7;2465:23;2461:32;2458:52;;;2506:1;2503;2496:12;2458:52;-1:-1:-1;2529:23:1;;2378:180;-1:-1:-1;2378:180:1:o;2563:247::-;2622:6;2675:2;2663:9;2654:7;2650:23;2646:32;2643:52;;;2691:1;2688;2681:12;2643:52;2730:9;2717:23;2749:31;2774:5;2749:31;:::i;3023:964::-;3148:6;3156;3164;3172;3180;3233:3;3221:9;3212:7;3208:23;3204:33;3201:53;;;3250:1;3247;3240:12;3201:53;3289:9;3276:23;3308:31;3333:5;3308:31;:::i;:::-;3358:5;-1:-1:-1;3415:2:1;3400:18;;3387:32;3428:33;3387:32;3428:33;:::i;:::-;3480:7;-1:-1:-1;3534:2:1;3519:18;;3506:32;;-1:-1:-1;3589:2:1;3574:18;;3561:32;3612:18;3642:14;;;3639:34;;;3669:1;3666;3659:12;3639:34;3707:6;3696:9;3692:22;3682:32;;3752:7;3745:4;3741:2;3737:13;3733:27;3723:55;;3774:1;3771;3764:12;3723:55;3814:2;3801:16;3840:2;3832:6;3829:14;3826:34;;;3856:1;3853;3846:12;3826:34;3901:7;3896:2;3887:6;3883:2;3879:15;3875:24;3872:37;3869:57;;;3922:1;3919;3912:12;3869:57;3023:964;;;;-1:-1:-1;3023:964:1;;-1:-1:-1;3953:2:1;3945:11;;3975:6;3023:964;-1:-1:-1;;;3023:964:1:o;4189:1259::-;4595:3;4590;4586:13;4578:6;4574:26;4563:9;4556:45;4537:4;4620:2;4658:3;4653:2;4642:9;4638:18;4631:31;4685:46;4726:3;4715:9;4711:19;4703:6;4685:46;:::i;:::-;4779:9;4771:6;4767:22;4762:2;4751:9;4747:18;4740:50;4813:33;4839:6;4831;4813:33;:::i;:::-;4877:2;4862:18;;4855:34;;;-1:-1:-1;;;;;4926:32:1;;4920:3;4905:19;;4898:61;4946:3;4975:19;;4968:35;;;5040:22;;;5034:3;5019:19;;5012:51;5112:13;;5134:22;;;5210:15;;;;-1:-1:-1;5172:15:1;;;;-1:-1:-1;5253:169:1;5267:6;5264:1;5261:13;5253:169;;;5328:13;;5316:26;;5397:15;;;;5362:12;;;;5289:1;5282:9;5253:169;;;-1:-1:-1;5439:3:1;;4189:1259;-1:-1:-1;;;;;;;;;;;;4189:1259:1:o;5654:156::-;5720:20;;5780:4;5769:16;;5759:27;;5749:55;;5800:1;5797;5790:12;5815:592;5917:6;5925;5933;5941;5949;5957;6010:3;5998:9;5989:7;5985:23;5981:33;5978:53;;;6027:1;6024;6017:12;5978:53;6066:9;6053:23;6085:31;6110:5;6085:31;:::i;:::-;6135:5;-1:-1:-1;6187:2:1;6172:18;;6159:32;;-1:-1:-1;6238:2:1;6223:18;;6210:32;;-1:-1:-1;6261:36:1;6293:2;6278:18;;6261:36;:::i;:::-;6251:46;;6344:3;6333:9;6329:19;6316:33;6306:43;;6396:3;6385:9;6381:19;6368:33;6358:43;;5815:592;;;;;;;;:::o;6412:734::-;6523:6;6531;6539;6547;6555;6563;6571;6624:3;6612:9;6603:7;6599:23;6595:33;6592:53;;;6641:1;6638;6631:12;6592:53;6680:9;6667:23;6699:31;6724:5;6699:31;:::i;:::-;6749:5;-1:-1:-1;6806:2:1;6791:18;;6778:32;6819:33;6778:32;6819:33;:::i;:::-;6871:7;-1:-1:-1;6925:2:1;6910:18;;6897:32;;-1:-1:-1;6976:2:1;6961:18;;6948:32;;-1:-1:-1;6999:37:1;7031:3;7016:19;;6999:37;:::i;:::-;6989:47;;7083:3;7072:9;7068:19;7055:33;7045:43;;7135:3;7124:9;7120:19;7107:33;7097:43;;6412:734;;;;;;;;;;:::o;7151:388::-;7219:6;7227;7280:2;7268:9;7259:7;7255:23;7251:32;7248:52;;;7296:1;7293;7286:12;7248:52;7335:9;7322:23;7354:31;7379:5;7354:31;:::i;:::-;7404:5;-1:-1:-1;7461:2:1;7446:18;;7433:32;7474:33;7433:32;7474:33;:::i;:::-;7526:7;7516:17;;;7151:388;;;;;:::o;7544:419::-;7611:6;7619;7672:2;7660:9;7651:7;7647:23;7643:32;7640:52;;;7688:1;7685;7678:12;7640:52;7727:9;7714:23;7746:31;7771:5;7746:31;:::i;:::-;7796:5;-1:-1:-1;7853:2:1;7838:18;;7825:32;7901:10;7888:24;;7876:37;;7866:65;;7927:1;7924;7917:12;8319:380;8398:1;8394:12;;;;8441;;;8462:61;;8516:4;8508:6;8504:17;8494:27;;8462:61;8569:2;8561:6;8558:14;8538:18;8535:38;8532:161;;;8615:10;8610:3;8606:20;8603:1;8596:31;8650:4;8647:1;8640:15;8678:4;8675:1;8668:15;8704:127;8765:10;8760:3;8756:20;8753:1;8746:31;8796:4;8793:1;8786:15;8820:4;8817:1;8810:15;8836:128;8876:3;8907:1;8903:6;8900:1;8897:13;8894:39;;;8913:18;;:::i;:::-;-1:-1:-1;8949:9:1;;8836:128::o;10093:734::-;-1:-1:-1;;;;;10400:15:1;;;10382:34;;10452:15;;10447:2;10432:18;;10425:43;10499:2;10484:18;;10477:34;;;10542:2;10527:18;;10520:34;;;10362:3;10585;10570:19;;10563:32;;;10611:19;;10604:35;;;10325:4;10632:6;10682;10676:3;10661:19;;10648:49;10747:1;10741:3;10732:6;10721:9;10717:22;10713:32;10706:43;10817:3;10810:2;10806:7;10801:2;10793:6;10789:15;10785:29;10774:9;10770:45;10766:55;10758:63;;10093:734;;;;;;;;;:::o;10832:184::-;10902:6;10955:2;10943:9;10934:7;10930:23;10926:32;10923:52;;;10971:1;10968;10961:12;10923:52;-1:-1:-1;10994:16:1;;10832:184;-1:-1:-1;10832:184:1:o;11426:125::-;11466:4;11494:1;11491;11488:8;11485:34;;;11499:18;;:::i;:::-;-1:-1:-1;11536:9:1;;11426:125::o;11688:127::-;11749:10;11744:3;11740:20;11737:1;11730:31;11780:4;11777:1;11770:15;11804:4;11801:1;11794:15;20888:297;21006:12;;21053:4;21042:16;;;21036:23;;21006:12;21071:16;;21068:111;;;-1:-1:-1;;21145:4:1;21141:17;;;;21138:1;21134:25;21130:38;21119:50;;20888:297;-1:-1:-1;20888:297:1:o;21937:127::-;21998:10;21993:3;21989:20;21986:1;21979:31;22029:4;22026:1;22019:15;22053:4;22050:1;22043:15;22069:217;22109:1;22135;22125:132;;22179:10;22174:3;22170:20;22167:1;22160:31;22214:4;22211:1;22204:15;22242:4;22239:1;22232:15;22125:132;-1:-1:-1;22271:9:1;;22069:217::o;23388:127::-;23449:10;23444:3;23440:20;23437:1;23430:31;23480:4;23477:1;23470:15;23504:4;23501:1;23494:15

Swarm Source

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