MATIC Price: $0.68 (+0.02%)
Gas: 68 GWei
 

Overview

Max Total Supply

300,000,000 ARES

Holders

169 (0.00%)

Total Transfers

-

Market

Price

$0.00 @ 0.000000 MATIC

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

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

OVERVIEW

Ares3 is a WEB3-integrated gaming platform. Provide the infrastructure for users to connect and compete with the WEB3 ecosystem.

Contract Source Code Verified (Exact Match)

Contract Name:
Ares3Network

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at polygonscan.com on 2023-07-14
*/

// SPDX-License-Identifier: MIT
// 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-1bbcd719a9.sol


pragma solidity ^0.8.9;









/// @custom:security-contact [email protected]
contract Ares3Network is ERC20, ERC20Burnable, ERC20Snapshot, Ownable, Pausable, ERC20Permit, ERC20Votes, ERC20FlashMint {
    constructor() ERC20("Ares3 Network", "ARES") ERC20Permit("Ares3 Network") {
        _mint(msg.sender, 300000000 * 10 ** decimals());
    }

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

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

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

    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":[],"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"}]

6101606040523480156200001257600080fd5b506040518060400160405280600d81526020016c4172657333204e6574776f726b60981b81525080604051806040016040528060018152602001603160f81b8152506040518060400160405280600d81526020016c4172657333204e6574776f726b60981b815250604051806040016040528060048152602001634152455360e01b8152508160039081620000a8919062000bd7565b506004620000b7828262000bd7565b505050620000d4620000ce620001de60201b60201c565b620001e2565b6009805460ff60a01b19169055620000fa82600a62000234602090811b6200112517901c565b610120526200011781600b62000234602090811b6200112517901c565b61014052815160208084019190912060e052815190820120610100524660a052620001a560e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c05250620001d833620001c26012600a62000db6565b620001d2906311e1a30062000dc7565b62000284565b62000e98565b3390565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600060208351101562000254576200024c836200029f565b90506200027e565b826200026b83620002eb60201b620011561760201c565b9062000278908262000bd7565b5060ff90505b92915050565b6200029b8282620002ee60201b620011591760201c565b5050565b600080829050601f81511115620002d6578260405163305a27a960e01b8152600401620002cd919062000de1565b60405180910390fd5b8051620002e38262000e31565b179392505050565b90565b620003058282620003a160201b620011e91760201c565b6001600160e01b03620003196200047c8216565b1115620003825760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b6064820152608401620002cd565b6200039b6010620012bc6200048260201b178362000497565b50505050565b6001600160a01b038216620003f95760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401620002cd565b620004076000838362000640565b80600260008282546200041b919062000e56565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36200029b6000838362000667565b60025490565b600062000490828462000e56565b9392505050565b82546000908190818115620004e65760008781526020902082016000190160408051808201909152905463ffffffff8116825264010000000090046001600160e01b03166020820152620004fb565b60408051808201909152600080825260208201525b905080602001516001600160e01b031693506200051984868860201c565b9250600082118015620005465750620005316200067f565b65ffffffffffff16816000015163ffffffff16145b156200059a5762000562836200069c60201b620012c81760201c565b60008881526020902083016000190180546001600160e01b03929092166401000000000263ffffffff90921691909117905562000636565b866040518060400160405280620005d3620005ba6200067f60201b60201c565b65ffffffffffff166200070b60201b620013351760201c565b63ffffffff168152602001620005f4866200069c60201b620012c81760201c565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b5050935093915050565b6200064a62000772565b62000662838383620007ca60201b6200139a1760201c565b505050565b620006628383836200083660201b620013e71760201c565b600062000697436200088260201b620014191760201c565b905090565b60006001600160e01b03821115620007075760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401620002cd565b5090565b600063ffffffff821115620007075760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401620002cd565b62000786600954600160a01b900460ff1690565b15620007c85760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401620002cd565b565b620007e28383836200066260201b620013b91760201c565b6001600160a01b0383166200080657620007fc82620008eb565b6200066262000923565b6001600160a01b0382166200082057620007fc83620008eb565b6200082b83620008eb565b6200066282620008eb565b6200084e8383836200066260201b620013b91760201c565b6001600160a01b038381166000908152600e6020526040808220548584168352912054620006629291821691168362000933565b600065ffffffffffff821115620007075760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401620002cd565b6001600160a01b0381166000908152600560209081526040808320918390529091205462000920919062000a6e565b62000a6e565b50565b620007c860066200091a60025490565b816001600160a01b0316836001600160a01b031614158015620009565750600081115b1562000662576001600160a01b03831615620009e3576001600160a01b0383166000908152600f6020908152604082208291620009a0919062000abd901b62001480178562000497565b91509150846001600160a01b031660008051602062003e328339815191528383604051620009d8929190918252602082015260400190565b60405180910390a250505b6001600160a01b0382161562000662576001600160a01b0382166000908152600f602090815260408220829162000a27919062000482901b620012bc178562000497565b91509150836001600160a01b031660008051602062003e32833981519152838360405162000a5f929190918252602082015260400190565b60405180910390a25050505050565b600062000a7a62000acb565b90508062000a888462000ae4565b101562000662578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b600062000490828462000e6c565b600062000697600862000b2f60201b6200148c1760201c565b8054600090810362000af857506000919050565b8154829062000b0a9060019062000e6c565b8154811062000b1d5762000b1d62000e82565b90600052602060002001549050919050565b5490565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168062000b5e57607f821691505b60208210810362000b7f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200066257600081815260208120601f850160051c8101602086101562000bae5750805b601f850160051c820191505b8181101562000bcf5782815560010162000bba565b505050505050565b81516001600160401b0381111562000bf35762000bf362000b33565b62000c0b8162000c04845462000b49565b8462000b85565b602080601f83116001811462000c43576000841562000c2a5750858301515b600019600386901b1c1916600185901b17855562000bcf565b600085815260208120601f198616915b8281101562000c745788860151825594840194600190910190840162000c53565b508582101562000c935787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000cfa57816000190482111562000cde5762000cde62000ca3565b8085161562000cec57918102915b93841c939080029062000cbe565b509250929050565b60008262000d13575060016200027e565b8162000d22575060006200027e565b816001811462000d3b576002811462000d465762000d66565b60019150506200027e565b60ff84111562000d5a5762000d5a62000ca3565b50506001821b6200027e565b5060208310610133831016604e8410600b841016171562000d8b575081810a6200027e565b62000d97838362000cb9565b806000190482111562000dae5762000dae62000ca3565b029392505050565b60006200049060ff84168362000d02565b80820281158282048414176200027e576200027e62000ca3565b600060208083528351808285015260005b8181101562000e105785810183015185820160400152820162000df2565b506000604082860101526040601f19601f8301168501019250505092915050565b8051602080830151919081101562000b7f5760001960209190910360031b1b16919050565b808201808211156200027e576200027e62000ca3565b818103818111156200027e576200027e62000ca3565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051610100516101205161014051612f3f62000ef36000396000610aee01526000610ac3015260006118b70152600061188f015260006117ea015260006118140152600061183e0152612f3f6000f3fe608060405234801561001057600080fd5b506004361061023d5760003560e01c8063715018a61161013b578063981b24d0116100b8578063d505accf1161007c578063d505accf14610500578063d9d98ce414610513578063dd62ed3e14610526578063f1127ed814610539578063f2fde38b1461057657600080fd5b8063981b24d0146104a15780639ab24eb0146104b4578063a457c2d7146104c7578063a9059cbb146104da578063c3cda520146104ed57600080fd5b80638da5cb5b116100ff5780638da5cb5b1461044e5780638e539e8c1461045f57806391ddadf41461047257806395d89b41146104915780639711715a1461049957600080fd5b8063715018a6146103fd57806379cc6790146104055780637ecebe00146104185780638456cb591461042b57806384b0196e1461043357600080fd5b806342966c68116101c95780635c975abb1161018d5780635c975abb146103745780635cffe9de14610386578063613255ab146103995780636fcfff45146103ac57806370a08231146103d457600080fd5b806342966c68146102ef5780634bf5d7e9146103025780634ee2cd7e1461030a578063587cde1e1461031d5780635c19a95c1461036157600080fd5b8063313ce56711610210578063313ce567146102a85780633644e515146102b757806339509351146102bf5780633a46b1a8146102d25780633f4ba83a146102e557600080fd5b806306fdde0314610242578063095ea7b31461026057806318160ddd1461028357806323b872dd14610295575b600080fd5b61024a610589565b604051610257919061292f565b60405180910390f35b61027361026e366004612957565b61061b565b6040519015158152602001610257565b6002545b604051908152602001610257565b6102736102a3366004612983565b610635565b60405160128152602001610257565b610287610659565b6102736102cd366004612957565b610668565b6102876102e0366004612957565b61068a565b6102ed610714565b005b6102ed6102fd3660046129c4565b610726565b61024a610733565b610287610318366004612957565b6107cb565b61034961032b3660046129dd565b6001600160a01b039081166000908152600e60205260409020541690565b6040516001600160a01b039091168152602001610257565b6102ed61036f3660046129dd565b610824565b600954600160a01b900460ff16610273565b6102736103943660046129fa565b61082e565b6102876103a73660046129dd565b610a12565b6103bf6103ba3660046129dd565b610a3a565b60405163ffffffff9091168152602001610257565b6102876103e23660046129dd565b6001600160a01b031660009081526020819052604090205490565b6102ed610a5c565b6102ed610413366004612957565b610a6e565b6102876104263660046129dd565b610a87565b6102ed610aa5565b61043b610ab5565b6040516102579796959493929190612a99565b6009546001600160a01b0316610349565b61028761046d3660046129c4565b610b3e565b61047a610ba5565b60405165ffffffffffff9091168152602001610257565b61024a610bb0565b6102ed610bbf565b6102876104af3660046129c4565b610bcf565b6102876104c23660046129dd565b610bfa565b6102736104d5366004612957565b610c7c565b6102736104e8366004612957565b610cf7565b6102ed6104fb366004612b40565b610d05565b6102ed61050e366004612b9a565b610e3b565b610287610521366004612957565b610f9f565b610287610534366004612c08565b611000565b61054c610547366004612c41565b61102b565b60408051825163ffffffff1681526020928301516001600160e01b03169281019290925201610257565b6102ed6105843660046129dd565b6110af565b60606003805461059890612c78565b80601f01602080910402602001604051908101604052809291908181526020018280546105c490612c78565b80156106115780601f106105e657610100808354040283529160200191610611565b820191906000526020600020905b8154815290600101906020018083116105f457829003601f168201915b5050505050905090565b600033610629818585611490565b60019150505b92915050565b6000336106438582856115b4565b61064e858585611628565b506001949350505050565b60006106636117dd565b905090565b60003361062981858561067b8383611000565b6106859190612cc2565b611490565b6000610694610ba5565b65ffffffffffff1682106106eb5760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b60448201526064015b60405180910390fd5b6001600160a01b0383166000908152600f6020526040902061070d9083611908565b9392505050565b61071c6119f1565b610724611a4b565b565b6107303382611aa0565b50565b60604361073e610ba5565b65ffffffffffff16146107935760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a2062726f6b656e20636c6f636b206d6f646500000060448201526064016106e2565b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b6001600160a01b0382166000908152600560205260408120819081906107f2908590611aaa565b9150915081610819576001600160a01b03851660009081526020819052604090205461081b565b805b95945050505050565b6107303382611ba0565b600061083985610a12565b84111561089c5760405162461bcd60e51b815260206004820152602b60248201527f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60448201526a30bc233630b9b42637b0b760a91b60648201526084016106e2565b60006108a88686610f9f565b90506108b48786611c19565b6040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038916906323e30c8b9061090c9033908b908b9088908c908c90600401612cd5565b6020604051808303816000875af115801561092b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094f9190612d31565b146109a85760405162461bcd60e51b8152602060048201526024808201527f4552433230466c6173684d696e743a20696e76616c69642072657475726e2076604482015263616c756560e01b60648201526084016106e2565b60006109be88306109b9858a612cc2565b6115b4565b8115806109d257506001600160a01b038116155b156109ef576109ea886109e58489612cc2565b611aa0565b610a04565b6109f98887611aa0565b610a04888284611628565b506001979650505050505050565b60006001600160a01b0382163014610a2b57600061062f565b60025461062f90600019612d4a565b6001600160a01b0381166000908152600f602052604081205461062f90611335565b610a646119f1565b6107246000611c23565b610a798233836115b4565b610a838282611aa0565b5050565b6001600160a01b0381166000908152600c602052604081205461062f565b610aad6119f1565b610724611c75565b600060608082808083610ae97f0000000000000000000000000000000000000000000000000000000000000000600a611cb8565b610b147f0000000000000000000000000000000000000000000000000000000000000000600b611cb8565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6000610b48610ba5565b65ffffffffffff168210610b9a5760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b60448201526064016106e2565b61062f601083611908565b600061066343611419565b60606004805461059890612c78565b610bc76119f1565b610730611d5c565b6000806000610bdf846006611aaa565b9150915081610bf057600254610bf2565b805b949350505050565b6001600160a01b0381166000908152600f60205260408120548015610c69576001600160a01b0383166000908152600f6020526040902080546000198301908110610c4757610c47612d73565b60009182526020909120015464010000000090046001600160e01b0316610c6c565b60005b6001600160e01b03169392505050565b60003381610c8a8286611000565b905083811015610cea5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016106e2565b61064e8286868403611490565b600033610629818585611628565b83421115610d555760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a207369676e6174757265206578706972656400000060448201526064016106e2565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090610dcf90610dc79060a00160405160208183030381529060405280519060200120611db6565b858585611de3565b9050610dda81611e0b565b8614610e285760405162461bcd60e51b815260206004820152601960248201527f4552433230566f7465733a20696e76616c6964206e6f6e63650000000000000060448201526064016106e2565b610e328188611ba0565b50505050505050565b83421115610e8b5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e6500000060448201526064016106e2565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610eba8c611e0b565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610f1582611db6565b90506000610f2582878787611de3565b9050896001600160a01b0316816001600160a01b031614610f885760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e6174757265000060448201526064016106e2565b610f938a8a8a611490565b50505050505050505050565b60006001600160a01b0383163014610ff95760405162461bcd60e51b815260206004820152601b60248201527f4552433230466c6173684d696e743a2077726f6e6720746f6b656e000000000060448201526064016106e2565b600061070d565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60408051808201909152600080825260208201526001600160a01b0383166000908152600f60205260409020805463ffffffff841690811061106f5761106f612d73565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160e01b0316918101919091529392505050565b6110b76119f1565b6001600160a01b03811661111c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106e2565b61073081611c23565b60006020835110156111415761113a83611e33565b905061062f565b8161114c8482612dd7565b5060ff905061062f565b90565b61116382826111e9565b6002546001600160e01b0310156111d55760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b60648201526084016106e2565b6111e360106112bc83611e71565b50505050565b6001600160a01b03821661123f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106e2565b61124b60008383611fe6565b806002600082825461125d9190612cc2565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610a8360008383611ff9565b600061070d8284612cc2565b60006001600160e01b038211156113315760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b60648201526084016106e2565b5090565b600063ffffffff8211156113315760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b60648201526084016106e2565b6001600160a01b0383166113be576113b182612004565b6113b9612036565b505050565b6001600160a01b0382166113d5576113b183612004565b6113de83612004565b6113b982612004565b6001600160a01b038381166000908152600e60205260408082205485841683529120546113b992918216911683612044565b600065ffffffffffff8211156113315760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b60648201526084016106e2565b600061070d8284612d4a565b5490565b6001600160a01b0383166114f25760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016106e2565b6001600160a01b0382166115535760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016106e2565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006115c08484611000565b905060001981146111e3578181101561161b5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106e2565b6111e38484848403611490565b6001600160a01b03831661168c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016106e2565b6001600160a01b0382166116ee5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016106e2565b6116f9838383611fe6565b6001600160a01b038316600090815260208190526040902054818110156117715760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016106e2565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36111e3848484611ff9565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561183657507f000000000000000000000000000000000000000000000000000000000000000046145b1561186057507f000000000000000000000000000000000000000000000000000000000000000090565b610663604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b81546000908181600581111561196257600061192384612181565b61192d9085612d4a565b600088815260209020909150869082015463ffffffff16111561195257809150611960565b61195d816001612cc2565b92505b505b808210156119af5760006119768383612269565b600088815260209020909150869082015463ffffffff16111561199b578091506119a9565b6119a6816001612cc2565b92505b50611962565b80156119db576000868152602090208101600019015464010000000090046001600160e01b03166119de565b60005b6001600160e01b03169695505050505050565b6009546001600160a01b031633146107245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e2565b611a53612284565b6009805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b610a8382826122d4565b60008060008411611af65760405162461bcd60e51b815260206004820152601660248201527504552433230536e617073686f743a20696420697320360541b60448201526064016106e2565b611afe6122ec565b841115611b4d5760405162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e7420696400000060448201526064016106e2565b6000611b5984866122f7565b84549091508103611b71576000809250925050611b99565b6001846001018281548110611b8857611b88612d73565b906000526020600020015492509250505b9250929050565b6001600160a01b038281166000818152600e60208181526040808420805485845282862054949093528787166001600160a01b03198416811790915590519190951694919391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46111e3828483612044565b610a838282611159565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611c7d6123a4565b6009805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611a833390565b606060ff8314611ccb5761113a836123f1565b818054611cd790612c78565b80601f0160208091040260200160405190810160405280929190818152602001828054611d0390612c78565b8015611d505780601f10611d2557610100808354040283529160200191611d50565b820191906000526020600020905b815481529060010190602001808311611d3357829003601f168201915b5050505050905061062f565b6000611d6c600880546001019055565b6000611d766122ec565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb6781604051611da991815260200190565b60405180910390a1919050565b600061062f611dc36117dd565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000611df487878787612430565b91509150611e01816124f4565b5095945050505050565b6001600160a01b0381166000908152600c602052604090208054600181018255905b50919050565b600080829050601f81511115611e5e578260405163305a27a960e01b81526004016106e2919061292f565b8051611e6982612e97565b179392505050565b82546000908190818115611ebe5760008781526020902082016000190160408051808201909152905463ffffffff8116825264010000000090046001600160e01b03166020820152611ed3565b60408051808201909152600080825260208201525b905080602001516001600160e01b03169350611ef384868863ffffffff16565b9250600082118015611f1d5750611f08610ba5565b65ffffffffffff16816000015163ffffffff16145b15611f6257611f2b836112c8565b60008881526020902083016000190180546001600160e01b03929092166401000000000263ffffffff909216919091179055611fdc565b866040518060400160405280611f86611f79610ba5565b65ffffffffffff16611335565b63ffffffff168152602001611f9a866112c8565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b5050935093915050565b611fee6123a4565b6113b983838361139a565b6113b98383836113e7565b6001600160a01b03811660009081526005602090815260408083209183905290912054610730919061263e565b61263e565b610724600661203160025490565b816001600160a01b0316836001600160a01b0316141580156120665750600081115b156113b9576001600160a01b038316156120f4576001600160a01b0383166000908152600f6020526040812081906120a19061148085611e71565b91509150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516120e9929190918252602082015260400190565b60405180910390a250505b6001600160a01b038216156113b9576001600160a01b0382166000908152600f60205260408120819061212a906112bc85611e71565b91509150836001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051612172929190918252602082015260400190565b60405180910390a25050505050565b60008160000361219357506000919050565b600060016121a084612688565b901c6001901b905060018184816121b9576121b9612ebb565b048201901c905060018184816121d1576121d1612ebb565b048201901c905060018184816121e9576121e9612ebb565b048201901c9050600181848161220157612201612ebb565b048201901c9050600181848161221957612219612ebb565b048201901c9050600181848161223157612231612ebb565b048201901c9050600181848161224957612249612ebb565b048201901c905061070d8182858161226357612263612ebb565b0461271c565b60006122786002848418612ed1565b61070d90848416612cc2565b600954600160a01b900460ff166107245760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106e2565b6122de8282612732565b6111e3601061148083611e71565b600061066360085490565b8154600090810361230a5750600061062f565b82546000905b808210156123575760006123248383612269565b6000878152602090209091508590820154111561234357809150612351565b61234e816001612cc2565b92505b50612310565b60008211801561238357508361238086612372600186612d4a565b600091825260209091200190565b54145b1561239c57612393600183612d4a565b9250505061062f565b50905061062f565b600954600160a01b900460ff16156107245760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106e2565b606060006123fe83612877565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561246757506000905060036124eb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156124bb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166124e4576000600192509250506124eb565b9150600090505b94509492505050565b600081600481111561250857612508612ef3565b036125105750565b600181600481111561252457612524612ef3565b036125715760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016106e2565b600281600481111561258557612585612ef3565b036125d25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106e2565b60038160048111156125e6576125e6612ef3565b036107305760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016106e2565b60006126486122ec565b9050806126548461289f565b10156113b9578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b600080608083901c1561269d57608092831c92015b604083901c156126af57604092831c92015b602083901c156126c157602092831c92015b601083901c156126d357601092831c92015b600883901c156126e557600892831c92015b600483901c156126f757600492831c92015b600283901c1561270957600292831c92015b600183901c1561062f5760010192915050565b600081831061272b578161070d565b5090919050565b6001600160a01b0382166127925760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016106e2565b61279e82600083611fe6565b6001600160a01b038216600090815260208190526040902054818110156128125760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016106e2565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36113b983600084611ff9565b600060ff8216601f81111561062f57604051632cd44ac360e21b815260040160405180910390fd5b805460009081036128b257506000919050565b815482906128c290600190612d4a565b815481106128d2576128d2612d73565b90600052602060002001549050919050565b919050565b6000815180845260005b8181101561290f576020818501810151868301820152016128f3565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061070d60208301846128e9565b6001600160a01b038116811461073057600080fd5b6000806040838503121561296a57600080fd5b823561297581612942565b946020939093013593505050565b60008060006060848603121561299857600080fd5b83356129a381612942565b925060208401356129b381612942565b929592945050506040919091013590565b6000602082840312156129d657600080fd5b5035919050565b6000602082840312156129ef57600080fd5b813561070d81612942565b600080600080600060808688031215612a1257600080fd5b8535612a1d81612942565b94506020860135612a2d81612942565b935060408601359250606086013567ffffffffffffffff80821115612a5157600080fd5b818801915088601f830112612a6557600080fd5b813581811115612a7457600080fd5b896020828501011115612a8657600080fd5b9699959850939650602001949392505050565b60ff60f81b881681526000602060e081840152612ab960e084018a6128e9565b8381036040850152612acb818a6128e9565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015612b1d57835183529284019291840191600101612b01565b50909c9b505050505050505050505050565b803560ff811681146128e457600080fd5b60008060008060008060c08789031215612b5957600080fd5b8635612b6481612942565b95506020870135945060408701359350612b8060608801612b2f565b92506080870135915060a087013590509295509295509295565b600080600080600080600060e0888a031215612bb557600080fd5b8735612bc081612942565b96506020880135612bd081612942565b95506040880135945060608801359350612bec60808901612b2f565b925060a0880135915060c0880135905092959891949750929550565b60008060408385031215612c1b57600080fd5b8235612c2681612942565b91506020830135612c3681612942565b809150509250929050565b60008060408385031215612c5457600080fd5b8235612c5f81612942565b9150602083013563ffffffff81168114612c3657600080fd5b600181811c90821680612c8c57607f821691505b602082108103611e2d57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561062f5761062f612cac565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c0840137600060c0848401015260c0601f19601f8501168301019050979650505050505050565b600060208284031215612d4357600080fd5b5051919050565b8181038181111561062f5761062f612cac565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b601f8211156113b957600081815260208120601f850160051c81016020861015612db05750805b601f850160051c820191505b81811015612dcf57828155600101612dbc565b505050505050565b815167ffffffffffffffff811115612df157612df1612d5d565b612e0581612dff8454612c78565b84612d89565b602080601f831160018114612e3a5760008415612e225750858301515b600019600386901b1c1916600185901b178555612dcf565b600085815260208120601f198616915b82811015612e6957888601518255948401946001909101908401612e4a565b5085821015612e875787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516020808301519190811015611e2d5760001960209190910360031b1b16919050565b634e487b7160e01b600052601260045260246000fd5b600082612eee57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220b9670446743e2c3973bf0fc1dde0ada07db74c16db67d57b39c94e316626208364736f6c63430008120033dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061023d5760003560e01c8063715018a61161013b578063981b24d0116100b8578063d505accf1161007c578063d505accf14610500578063d9d98ce414610513578063dd62ed3e14610526578063f1127ed814610539578063f2fde38b1461057657600080fd5b8063981b24d0146104a15780639ab24eb0146104b4578063a457c2d7146104c7578063a9059cbb146104da578063c3cda520146104ed57600080fd5b80638da5cb5b116100ff5780638da5cb5b1461044e5780638e539e8c1461045f57806391ddadf41461047257806395d89b41146104915780639711715a1461049957600080fd5b8063715018a6146103fd57806379cc6790146104055780637ecebe00146104185780638456cb591461042b57806384b0196e1461043357600080fd5b806342966c68116101c95780635c975abb1161018d5780635c975abb146103745780635cffe9de14610386578063613255ab146103995780636fcfff45146103ac57806370a08231146103d457600080fd5b806342966c68146102ef5780634bf5d7e9146103025780634ee2cd7e1461030a578063587cde1e1461031d5780635c19a95c1461036157600080fd5b8063313ce56711610210578063313ce567146102a85780633644e515146102b757806339509351146102bf5780633a46b1a8146102d25780633f4ba83a146102e557600080fd5b806306fdde0314610242578063095ea7b31461026057806318160ddd1461028357806323b872dd14610295575b600080fd5b61024a610589565b604051610257919061292f565b60405180910390f35b61027361026e366004612957565b61061b565b6040519015158152602001610257565b6002545b604051908152602001610257565b6102736102a3366004612983565b610635565b60405160128152602001610257565b610287610659565b6102736102cd366004612957565b610668565b6102876102e0366004612957565b61068a565b6102ed610714565b005b6102ed6102fd3660046129c4565b610726565b61024a610733565b610287610318366004612957565b6107cb565b61034961032b3660046129dd565b6001600160a01b039081166000908152600e60205260409020541690565b6040516001600160a01b039091168152602001610257565b6102ed61036f3660046129dd565b610824565b600954600160a01b900460ff16610273565b6102736103943660046129fa565b61082e565b6102876103a73660046129dd565b610a12565b6103bf6103ba3660046129dd565b610a3a565b60405163ffffffff9091168152602001610257565b6102876103e23660046129dd565b6001600160a01b031660009081526020819052604090205490565b6102ed610a5c565b6102ed610413366004612957565b610a6e565b6102876104263660046129dd565b610a87565b6102ed610aa5565b61043b610ab5565b6040516102579796959493929190612a99565b6009546001600160a01b0316610349565b61028761046d3660046129c4565b610b3e565b61047a610ba5565b60405165ffffffffffff9091168152602001610257565b61024a610bb0565b6102ed610bbf565b6102876104af3660046129c4565b610bcf565b6102876104c23660046129dd565b610bfa565b6102736104d5366004612957565b610c7c565b6102736104e8366004612957565b610cf7565b6102ed6104fb366004612b40565b610d05565b6102ed61050e366004612b9a565b610e3b565b610287610521366004612957565b610f9f565b610287610534366004612c08565b611000565b61054c610547366004612c41565b61102b565b60408051825163ffffffff1681526020928301516001600160e01b03169281019290925201610257565b6102ed6105843660046129dd565b6110af565b60606003805461059890612c78565b80601f01602080910402602001604051908101604052809291908181526020018280546105c490612c78565b80156106115780601f106105e657610100808354040283529160200191610611565b820191906000526020600020905b8154815290600101906020018083116105f457829003601f168201915b5050505050905090565b600033610629818585611490565b60019150505b92915050565b6000336106438582856115b4565b61064e858585611628565b506001949350505050565b60006106636117dd565b905090565b60003361062981858561067b8383611000565b6106859190612cc2565b611490565b6000610694610ba5565b65ffffffffffff1682106106eb5760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b60448201526064015b60405180910390fd5b6001600160a01b0383166000908152600f6020526040902061070d9083611908565b9392505050565b61071c6119f1565b610724611a4b565b565b6107303382611aa0565b50565b60604361073e610ba5565b65ffffffffffff16146107935760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a2062726f6b656e20636c6f636b206d6f646500000060448201526064016106e2565b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b6001600160a01b0382166000908152600560205260408120819081906107f2908590611aaa565b9150915081610819576001600160a01b03851660009081526020819052604090205461081b565b805b95945050505050565b6107303382611ba0565b600061083985610a12565b84111561089c5760405162461bcd60e51b815260206004820152602b60248201527f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60448201526a30bc233630b9b42637b0b760a91b60648201526084016106e2565b60006108a88686610f9f565b90506108b48786611c19565b6040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038916906323e30c8b9061090c9033908b908b9088908c908c90600401612cd5565b6020604051808303816000875af115801561092b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094f9190612d31565b146109a85760405162461bcd60e51b8152602060048201526024808201527f4552433230466c6173684d696e743a20696e76616c69642072657475726e2076604482015263616c756560e01b60648201526084016106e2565b60006109be88306109b9858a612cc2565b6115b4565b8115806109d257506001600160a01b038116155b156109ef576109ea886109e58489612cc2565b611aa0565b610a04565b6109f98887611aa0565b610a04888284611628565b506001979650505050505050565b60006001600160a01b0382163014610a2b57600061062f565b60025461062f90600019612d4a565b6001600160a01b0381166000908152600f602052604081205461062f90611335565b610a646119f1565b6107246000611c23565b610a798233836115b4565b610a838282611aa0565b5050565b6001600160a01b0381166000908152600c602052604081205461062f565b610aad6119f1565b610724611c75565b600060608082808083610ae97f4172657333204e6574776f726b0000000000000000000000000000000000000d600a611cb8565b610b147f3100000000000000000000000000000000000000000000000000000000000001600b611cb8565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6000610b48610ba5565b65ffffffffffff168210610b9a5760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b60448201526064016106e2565b61062f601083611908565b600061066343611419565b60606004805461059890612c78565b610bc76119f1565b610730611d5c565b6000806000610bdf846006611aaa565b9150915081610bf057600254610bf2565b805b949350505050565b6001600160a01b0381166000908152600f60205260408120548015610c69576001600160a01b0383166000908152600f6020526040902080546000198301908110610c4757610c47612d73565b60009182526020909120015464010000000090046001600160e01b0316610c6c565b60005b6001600160e01b03169392505050565b60003381610c8a8286611000565b905083811015610cea5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016106e2565b61064e8286868403611490565b600033610629818585611628565b83421115610d555760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a207369676e6174757265206578706972656400000060448201526064016106e2565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090610dcf90610dc79060a00160405160208183030381529060405280519060200120611db6565b858585611de3565b9050610dda81611e0b565b8614610e285760405162461bcd60e51b815260206004820152601960248201527f4552433230566f7465733a20696e76616c6964206e6f6e63650000000000000060448201526064016106e2565b610e328188611ba0565b50505050505050565b83421115610e8b5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e6500000060448201526064016106e2565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610eba8c611e0b565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610f1582611db6565b90506000610f2582878787611de3565b9050896001600160a01b0316816001600160a01b031614610f885760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e6174757265000060448201526064016106e2565b610f938a8a8a611490565b50505050505050505050565b60006001600160a01b0383163014610ff95760405162461bcd60e51b815260206004820152601b60248201527f4552433230466c6173684d696e743a2077726f6e6720746f6b656e000000000060448201526064016106e2565b600061070d565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60408051808201909152600080825260208201526001600160a01b0383166000908152600f60205260409020805463ffffffff841690811061106f5761106f612d73565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160e01b0316918101919091529392505050565b6110b76119f1565b6001600160a01b03811661111c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106e2565b61073081611c23565b60006020835110156111415761113a83611e33565b905061062f565b8161114c8482612dd7565b5060ff905061062f565b90565b61116382826111e9565b6002546001600160e01b0310156111d55760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b60648201526084016106e2565b6111e360106112bc83611e71565b50505050565b6001600160a01b03821661123f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106e2565b61124b60008383611fe6565b806002600082825461125d9190612cc2565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610a8360008383611ff9565b600061070d8284612cc2565b60006001600160e01b038211156113315760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b60648201526084016106e2565b5090565b600063ffffffff8211156113315760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b60648201526084016106e2565b6001600160a01b0383166113be576113b182612004565b6113b9612036565b505050565b6001600160a01b0382166113d5576113b183612004565b6113de83612004565b6113b982612004565b6001600160a01b038381166000908152600e60205260408082205485841683529120546113b992918216911683612044565b600065ffffffffffff8211156113315760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b60648201526084016106e2565b600061070d8284612d4a565b5490565b6001600160a01b0383166114f25760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016106e2565b6001600160a01b0382166115535760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016106e2565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006115c08484611000565b905060001981146111e3578181101561161b5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106e2565b6111e38484848403611490565b6001600160a01b03831661168c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016106e2565b6001600160a01b0382166116ee5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016106e2565b6116f9838383611fe6565b6001600160a01b038316600090815260208190526040902054818110156117715760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016106e2565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36111e3848484611ff9565b6000306001600160a01b037f000000000000000000000000181feaecca4a69a793272ea06df40edf2dd0804c1614801561183657507f000000000000000000000000000000000000000000000000000000000000008946145b1561186057507f72e708f42532c76954db7d12d522c6735eecfd18fa6bd6aaea7bd50613ab035090565b610663604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f56ab7392c667cabe203d2b98f0541f21c51a6b398d28eabb236d230eed177e36918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b81546000908181600581111561196257600061192384612181565b61192d9085612d4a565b600088815260209020909150869082015463ffffffff16111561195257809150611960565b61195d816001612cc2565b92505b505b808210156119af5760006119768383612269565b600088815260209020909150869082015463ffffffff16111561199b578091506119a9565b6119a6816001612cc2565b92505b50611962565b80156119db576000868152602090208101600019015464010000000090046001600160e01b03166119de565b60005b6001600160e01b03169695505050505050565b6009546001600160a01b031633146107245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e2565b611a53612284565b6009805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b610a8382826122d4565b60008060008411611af65760405162461bcd60e51b815260206004820152601660248201527504552433230536e617073686f743a20696420697320360541b60448201526064016106e2565b611afe6122ec565b841115611b4d5760405162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e7420696400000060448201526064016106e2565b6000611b5984866122f7565b84549091508103611b71576000809250925050611b99565b6001846001018281548110611b8857611b88612d73565b906000526020600020015492509250505b9250929050565b6001600160a01b038281166000818152600e60208181526040808420805485845282862054949093528787166001600160a01b03198416811790915590519190951694919391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46111e3828483612044565b610a838282611159565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611c7d6123a4565b6009805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611a833390565b606060ff8314611ccb5761113a836123f1565b818054611cd790612c78565b80601f0160208091040260200160405190810160405280929190818152602001828054611d0390612c78565b8015611d505780601f10611d2557610100808354040283529160200191611d50565b820191906000526020600020905b815481529060010190602001808311611d3357829003601f168201915b5050505050905061062f565b6000611d6c600880546001019055565b6000611d766122ec565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb6781604051611da991815260200190565b60405180910390a1919050565b600061062f611dc36117dd565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000611df487878787612430565b91509150611e01816124f4565b5095945050505050565b6001600160a01b0381166000908152600c602052604090208054600181018255905b50919050565b600080829050601f81511115611e5e578260405163305a27a960e01b81526004016106e2919061292f565b8051611e6982612e97565b179392505050565b82546000908190818115611ebe5760008781526020902082016000190160408051808201909152905463ffffffff8116825264010000000090046001600160e01b03166020820152611ed3565b60408051808201909152600080825260208201525b905080602001516001600160e01b03169350611ef384868863ffffffff16565b9250600082118015611f1d5750611f08610ba5565b65ffffffffffff16816000015163ffffffff16145b15611f6257611f2b836112c8565b60008881526020902083016000190180546001600160e01b03929092166401000000000263ffffffff909216919091179055611fdc565b866040518060400160405280611f86611f79610ba5565b65ffffffffffff16611335565b63ffffffff168152602001611f9a866112c8565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b5050935093915050565b611fee6123a4565b6113b983838361139a565b6113b98383836113e7565b6001600160a01b03811660009081526005602090815260408083209183905290912054610730919061263e565b61263e565b610724600661203160025490565b816001600160a01b0316836001600160a01b0316141580156120665750600081115b156113b9576001600160a01b038316156120f4576001600160a01b0383166000908152600f6020526040812081906120a19061148085611e71565b91509150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516120e9929190918252602082015260400190565b60405180910390a250505b6001600160a01b038216156113b9576001600160a01b0382166000908152600f60205260408120819061212a906112bc85611e71565b91509150836001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051612172929190918252602082015260400190565b60405180910390a25050505050565b60008160000361219357506000919050565b600060016121a084612688565b901c6001901b905060018184816121b9576121b9612ebb565b048201901c905060018184816121d1576121d1612ebb565b048201901c905060018184816121e9576121e9612ebb565b048201901c9050600181848161220157612201612ebb565b048201901c9050600181848161221957612219612ebb565b048201901c9050600181848161223157612231612ebb565b048201901c9050600181848161224957612249612ebb565b048201901c905061070d8182858161226357612263612ebb565b0461271c565b60006122786002848418612ed1565b61070d90848416612cc2565b600954600160a01b900460ff166107245760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106e2565b6122de8282612732565b6111e3601061148083611e71565b600061066360085490565b8154600090810361230a5750600061062f565b82546000905b808210156123575760006123248383612269565b6000878152602090209091508590820154111561234357809150612351565b61234e816001612cc2565b92505b50612310565b60008211801561238357508361238086612372600186612d4a565b600091825260209091200190565b54145b1561239c57612393600183612d4a565b9250505061062f565b50905061062f565b600954600160a01b900460ff16156107245760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106e2565b606060006123fe83612877565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561246757506000905060036124eb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156124bb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166124e4576000600192509250506124eb565b9150600090505b94509492505050565b600081600481111561250857612508612ef3565b036125105750565b600181600481111561252457612524612ef3565b036125715760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016106e2565b600281600481111561258557612585612ef3565b036125d25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106e2565b60038160048111156125e6576125e6612ef3565b036107305760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016106e2565b60006126486122ec565b9050806126548461289f565b10156113b9578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b600080608083901c1561269d57608092831c92015b604083901c156126af57604092831c92015b602083901c156126c157602092831c92015b601083901c156126d357601092831c92015b600883901c156126e557600892831c92015b600483901c156126f757600492831c92015b600283901c1561270957600292831c92015b600183901c1561062f5760010192915050565b600081831061272b578161070d565b5090919050565b6001600160a01b0382166127925760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016106e2565b61279e82600083611fe6565b6001600160a01b038216600090815260208190526040902054818110156128125760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016106e2565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36113b983600084611ff9565b600060ff8216601f81111561062f57604051632cd44ac360e21b815260040160405180910390fd5b805460009081036128b257506000919050565b815482906128c290600190612d4a565b815481106128d2576128d2612d73565b90600052602060002001549050919050565b919050565b6000815180845260005b8181101561290f576020818501810151868301820152016128f3565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061070d60208301846128e9565b6001600160a01b038116811461073057600080fd5b6000806040838503121561296a57600080fd5b823561297581612942565b946020939093013593505050565b60008060006060848603121561299857600080fd5b83356129a381612942565b925060208401356129b381612942565b929592945050506040919091013590565b6000602082840312156129d657600080fd5b5035919050565b6000602082840312156129ef57600080fd5b813561070d81612942565b600080600080600060808688031215612a1257600080fd5b8535612a1d81612942565b94506020860135612a2d81612942565b935060408601359250606086013567ffffffffffffffff80821115612a5157600080fd5b818801915088601f830112612a6557600080fd5b813581811115612a7457600080fd5b896020828501011115612a8657600080fd5b9699959850939650602001949392505050565b60ff60f81b881681526000602060e081840152612ab960e084018a6128e9565b8381036040850152612acb818a6128e9565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015612b1d57835183529284019291840191600101612b01565b50909c9b505050505050505050505050565b803560ff811681146128e457600080fd5b60008060008060008060c08789031215612b5957600080fd5b8635612b6481612942565b95506020870135945060408701359350612b8060608801612b2f565b92506080870135915060a087013590509295509295509295565b600080600080600080600060e0888a031215612bb557600080fd5b8735612bc081612942565b96506020880135612bd081612942565b95506040880135945060608801359350612bec60808901612b2f565b925060a0880135915060c0880135905092959891949750929550565b60008060408385031215612c1b57600080fd5b8235612c2681612942565b91506020830135612c3681612942565b809150509250929050565b60008060408385031215612c5457600080fd5b8235612c5f81612942565b9150602083013563ffffffff81168114612c3657600080fd5b600181811c90821680612c8c57607f821691505b602082108103611e2d57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561062f5761062f612cac565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c0840137600060c0848401015260c0601f19601f8501168301019050979650505050505050565b600060208284031215612d4357600080fd5b5051919050565b8181038181111561062f5761062f612cac565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b601f8211156113b957600081815260208120601f850160051c81016020861015612db05750805b601f850160051c820191505b81811015612dcf57828155600101612dbc565b505050505050565b815167ffffffffffffffff811115612df157612df1612d5d565b612e0581612dff8454612c78565b84612d89565b602080601f831160018114612e3a5760008415612e225750858301515b600019600386901b1c1916600185901b178555612dcf565b600085815260208120601f198616915b82811015612e6957888601518255948401946001909101908401612e4a565b5085821015612e875787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516020808301519190811015611e2d5760001960209190910360031b1b16919050565b634e487b7160e01b600052601260045260246000fd5b600082612eee57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220b9670446743e2c3973bf0fc1dde0ada07db74c16db67d57b39c94e316626208364736f6c63430008120033

Deployed Bytecode Sourcemap

144286:1304:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103767:100;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;106127:201;;;;;;:::i;:::-;;:::i;:::-;;;1288:14:1;;1281:22;1263:41;;1251:2;1236:18;106127:201:0;1123:187:1;104896:108:0;104984:12;;104896:108;;;1461:25:1;;;1449:2;1434:18;104896:108:0;1315:177:1;106908:261:0;;;;;;:::i;:::-;;:::i;104738:93::-;;;104821:2;2100:36:1;;2088:2;2073:18;104738:93:0;1958:184:1;122387:115:0;;;:::i;107578:238::-;;;;;;:::i;:::-;;:::i;126265:251::-;;;;;;:::i;:::-;;:::i;144706:65::-;;;:::i;:::-;;143571:91;;;;;;:::i;:::-;;:::i;124802:258::-;;;:::i;139121:266::-;;;;;;:::i;:::-;;:::i;125616:128::-;;;;;;:::i;:::-;-1:-1:-1;;;;;125717:19:0;;;125690:7;125717:19;;;:10;:19;;;;;;;;125616:128;;;;-1:-1:-1;;;;;2930:32:1;;;2912:51;;2900:2;2885:18;125616:128:0;2766:203:1;129139:114:0;;;;;;:::i;:::-;;:::i;94340:86::-;94411:7;;-1:-1:-1;;;94411:7:0;;;;94340:86;;118608:959;;;;;;:::i;:::-;;:::i;115694:178::-;;;;;;:::i;:::-;;:::i;125372:151::-;;;;;;:::i;:::-;;:::i;:::-;;;4117:10:1;4105:23;;;4087:42;;4075:2;4060:18;125372:151:0;3943:192:1;105067:127:0;;;;;;:::i;:::-;-1:-1:-1;;;;;105168:18:0;105141:7;105168:18;;;;;;;;;;;;105067:127;97204:103;;;:::i;143981:164::-;;;;;;:::i;:::-;;:::i;122129:128::-;;;;;;:::i;:::-;;:::i;144637:61::-;;;:::i;87044:657::-;;;:::i;:::-;;;;;;;;;;;;;:::i;96563:87::-;96636:6;;-1:-1:-1;;;;;96636:6:0;96563:87;;126788:242;;;;;;:::i;:::-;;:::i;124564:120::-;;;:::i;:::-;;;5578:14:1;5566:27;;;5548:46;;5536:2;5521:18;124564:120:0;5404:196:1;103986:104:0;;;:::i;144562:67::-;;;:::i;139491:234::-;;;;;;:::i;:::-;;:::i;125828:248::-;;;;;;:::i;:::-;;:::i;108319:436::-;;;;;;:::i;:::-;;:::i;105400:193::-;;;;;;:::i;:::-;;:::i;129335:591::-;;;;;;:::i;:::-;;:::i;121418:645::-;;;;;;:::i;:::-;;:::i;116248:219::-;;;;;;:::i;:::-;;:::i;105656:151::-;;;;;;:::i;:::-;;:::i;125142:150::-;;;;;;:::i;:::-;;:::i;:::-;;;;8143:13:1;;8158:10;8139:30;8121:49;;8230:4;8218:17;;;8212:24;-1:-1:-1;;;;;8208:50:1;8186:20;;;8179:80;;;;8094:18;125142:150:0;7919:346:1;97462:201:0;;;;;;:::i;:::-;;:::i;103767:100::-;103821:13;103854:5;103847:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103767:100;:::o;106127:201::-;106210:4;92527:10;106266:32;92527:10;106282:7;106291:6;106266:8;:32::i;:::-;106316:4;106309:11;;;106127:201;;;;;:::o;106908:261::-;107005:4;92527:10;107063:38;107079:4;92527:10;107094:6;107063:15;:38::i;:::-;107112:27;107122:4;107128:2;107132:6;107112:9;:27::i;:::-;-1:-1:-1;107157:4:0;;106908:261;-1:-1:-1;;;;106908:261:0:o;122387:115::-;122447:7;122474:20;:18;:20::i;:::-;122467:27;;122387:115;:::o;107578:238::-;107666:4;92527:10;107722:64;92527:10;107738:7;107775:10;107747:25;92527:10;107738:7;107747:9;:25::i;:::-;:38;;;;:::i;:::-;107722:8;:64::i;126265:251::-;126361:7;126401;:5;:7::i;:::-;126389:19;;:9;:19;126381:57;;;;-1:-1:-1;;;126381:57:0;;9119:2:1;126381:57:0;;;9101:21:1;9158:2;9138:18;;;9131:30;-1:-1:-1;;;9177:18:1;;;9170:55;9242:18;;126381:57:0;;;;;;;;;-1:-1:-1;;;;;126475:21:0;;;;;;:12;:21;;;;;126456:52;;126498:9;126456:18;:52::i;:::-;126449:59;126265:251;-1:-1:-1;;;126265:251:0:o;144706:65::-;96449:13;:11;:13::i;:::-;144753:10:::1;:8;:10::i;:::-;144706:65::o:0;143571:91::-;143627:27;92527:10;143647:6;143627:5;:27::i;:::-;143571:91;:::o;124802:258::-;124862:13;124957:12;124946:7;:5;:7::i;:::-;:23;;;124938:65;;;;-1:-1:-1;;;124938:65:0;;9473:2:1;124938:65:0;;;9455:21:1;9512:2;9492:18;;;9485:30;9551:31;9531:18;;;9524:59;9600:18;;124938:65:0;9271:353:1;124938:65:0;-1:-1:-1;125014:38:0;;;;;;;;;;;;;;;;;;124802:258::o;139121:266::-;-1:-1:-1;;;;;139285:33:0;;139208:7;139285:33;;;:24;:33;;;;;139208:7;;;;139264:55;;139273:10;;139264:8;:55::i;:::-;139228:91;;;;139339:11;:40;;-1:-1:-1;;;;;105168:18:0;;105141:7;105168:18;;;;;;;;;;;139339:40;;;139353:5;139339:40;139332:47;139121:266;-1:-1:-1;;;;;139121:266:0:o;129139:114::-;129211:34;92527:10;129235:9;129211;:34::i;118608:959::-;118787:4;118822:19;118835:5;118822:12;:19::i;:::-;118812:6;:29;;118804:85;;;;-1:-1:-1;;;118804:85:0;;9831:2:1;118804:85:0;;;9813:21:1;9870:2;9850:18;;;9843:30;9909:34;9889:18;;;9882:62;-1:-1:-1;;;9960:18:1;;;9953:41;10011:19;;118804:85:0;9629:407:1;118804:85:0;118900:11;118914:23;118923:5;118930:6;118914:8;:23::i;:::-;118900:37;;118948:32;118962:8;118973:6;118948:5;:32::i;:::-;119013:58;;-1:-1:-1;;;119013:58:0;;115431:45;;-1:-1:-1;;;;;119013:20:0;;;;;:58;;119034:10;;119046:5;;119053:6;;119061:3;;119066:4;;;;119013:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:75;118991:161;;;;-1:-1:-1;;;118991:161:0;;11171:2:1;118991:161:0;;;11153:21:1;11210:2;11190:18;;;11183:30;11249:34;11229:18;;;11222:62;-1:-1:-1;;;11300:18:1;;;11293:34;11344:19;;118991:161:0;10969:400:1;118991:161:0;119163:24;119220:63;119244:8;119263:4;119270:12;119279:3;119270:6;:12;:::i;:::-;119220:15;:63::i;:::-;119298:8;;;:42;;-1:-1:-1;;;;;;119310:30:0;;;119298:42;119294:244;;;119357:38;119371:8;119382:12;119391:3;119382:6;:12;:::i;:::-;119357:5;:38::i;:::-;119294:244;;;119428:32;119442:8;119453:6;119428:5;:32::i;:::-;119475:51;119493:8;119504:16;119522:3;119475:9;:51::i;:::-;-1:-1:-1;119555:4:0;;118608:959;-1:-1:-1;;;;;;;118608:959:0:o;115694:178::-;115769:7;-1:-1:-1;;;;;115796:22:0;;115813:4;115796:22;:68;;115863:1;115796:68;;;104984:12;;115821:39;;-1:-1:-1;;115821:39:0;:::i;125372:151::-;-1:-1:-1;;;;;125486:21:0;;125442:6;125486:21;;;:12;:21;;;;;:28;125468:47;;:17;:47::i;97204:103::-;96449:13;:11;:13::i;:::-;97269:30:::1;97296:1;97269:18;:30::i;143981:164::-:0;144058:46;144074:7;92527:10;144097:6;144058:15;:46::i;:::-;144115:22;144121:7;144130:6;144115:5;:22::i;:::-;143981:164;;:::o;122129:128::-;-1:-1:-1;;;;;122225:14:0;;122198:7;122225:14;;;:7;:14;;;;;47403;122225:24;47311:114;144637:61;96449:13;:11;:13::i;:::-;144682:8:::1;:6;:8::i;87044:657::-:0;87165:13;87193:18;;87165:13;;;87193:18;87467:41;:5;87494:13;87467:26;:41::i;:::-;87523:47;:8;87553:16;87523:29;:47::i;:::-;87666:16;;;87649:1;87666:16;;;;;;;;;-1:-1:-1;;;87414:279:0;;;-1:-1:-1;87414:279:0;;-1:-1:-1;87585:13:0;;-1:-1:-1;87621:4:0;;-1:-1:-1;87649:1:0;-1:-1:-1;87666:16:0;-1:-1:-1;87414:279:0;-1:-1:-1;87044:657:0:o;126788:242::-;126873:7;126913;:5;:7::i;:::-;126901:19;;:9;:19;126893:57;;;;-1:-1:-1;;;126893:57:0;;9119:2:1;126893:57:0;;;9101:21:1;9158:2;9138:18;;;9131:30;-1:-1:-1;;;9177:18:1;;;9170:55;9242:18;;126893:57:0;8917:349:1;126893:57:0;126968:54;126987:23;127012:9;126968:18;:54::i;124564:120::-;124619:6;124645:31;124663:12;124645:17;:31::i;103986:104::-;104042:13;104075:7;104068:14;;;;;:::i;144562:67::-;96449:13;:11;:13::i;:::-;144610:11:::1;:9;:11::i;139491:234::-:0;139563:7;139584:16;139602:13;139619:43;139628:10;139640:21;139619:8;:43::i;:::-;139583:79;;;;139682:11;:35;;104984:12;;139682:35;;;139696:5;139682:35;139675:42;139491:234;-1:-1:-1;;;;139491:234:0:o;125828:248::-;-1:-1:-1;;;;;125935:21:0;;125901:7;125935:21;;;:12;:21;;;;;:28;126006:8;;:51;;-1:-1:-1;;;;;126021:21:0;;;;;;:12;:21;;;;;:30;;-1:-1:-1;;126043:7:0;;;126021:30;;;;;;:::i;:::-;;;;;;;;;;:36;;;;-1:-1:-1;;;;;126021:36:0;126006:51;;;126017:1;126006:51;-1:-1:-1;;;;;125999:58:0;;125828:248;-1:-1:-1;;;125828:248:0:o;108319:436::-;108412:4;92527:10;108412:4;108495:25;92527:10;108512:7;108495:9;:25::i;:::-;108468:52;;108559:15;108539:16;:35;;108531:85;;;;-1:-1:-1;;;108531:85:0;;11973:2:1;108531:85:0;;;11955:21:1;12012:2;11992:18;;;11985:30;12051:34;12031:18;;;12024:62;-1:-1:-1;;;12102:18:1;;;12095:35;12147:19;;108531:85:0;11771:401:1;108531:85:0;108652:60;108661:5;108668:7;108696:15;108677:16;:34;108652:8;:60::i;105400:193::-;105479:4;92527:10;105535:28;92527:10;105552:2;105556:6;105535:9;:28::i;129335:591::-;129562:6;129543:15;:25;;129535:67;;;;-1:-1:-1;;;129535:67:0;;12379:2:1;129535:67:0;;;12361:21:1;12418:2;12398:18;;;12391:30;12457:31;12437:18;;;12430:59;12506:18;;129535:67:0;12177:353:1;129535:67:0;129685:58;;;124177:71;129685:58;;;12766:25:1;-1:-1:-1;;;;;12827:32:1;;12807:18;;;12800:60;;;;12876:18;;;12869:34;;;12919:18;;;12912:34;;;129613:14:0;;129630:174;;129658:87;;12738:19:1;;129685:58:0;;;;;;;;;;;;129675:69;;;;;;129658:16;:87::i;:::-;129760:1;129776;129792;129630:13;:174::i;:::-;129613:191;;129832:17;129842:6;129832:9;:17::i;:::-;129823:5;:26;129815:64;;;;-1:-1:-1;;;129815:64:0;;13159:2:1;129815:64:0;;;13141:21:1;13198:2;13178:18;;;13171:30;13237:27;13217:18;;;13210:55;13282:18;;129815:64:0;12957:349:1;129815:64:0;129890:28;129900:6;129908:9;129890;:28::i;:::-;129524:402;129335:591;;;;;;:::o;121418:645::-;121662:8;121643:15;:27;;121635:69;;;;-1:-1:-1;;;121635:69:0;;13513:2:1;121635:69:0;;;13495:21:1;13552:2;13532:18;;;13525:30;13591:31;13571:18;;;13564:59;13640:18;;121635:69:0;13311:353:1;121635:69:0;121717:18;120593:95;121777:5;121784:7;121793:5;121800:16;121810:5;121800:9;:16::i;:::-;121748:79;;;;;;13956:25:1;;;;-1:-1:-1;;;;;14055:15:1;;;14035:18;;;14028:43;14107:15;;;;14087:18;;;14080:43;14139:18;;;14132:34;14182:19;;;14175:35;14226:19;;;14219:35;;;13928:19;;121748:79:0;;;;;;;;;;;;121738:90;;;;;;121717:111;;121841:12;121856:28;121873:10;121856:16;:28::i;:::-;121841:43;;121897:14;121914:28;121928:4;121934:1;121937;121940;121914:13;:28::i;:::-;121897:45;;121971:5;-1:-1:-1;;;;;121961:15:0;:6;-1:-1:-1;;;;;121961:15:0;;121953:58;;;;-1:-1:-1;;;121953:58:0;;14467:2:1;121953:58:0;;;14449:21:1;14506:2;14486:18;;;14479:30;14545:32;14525:18;;;14518:60;14595:18;;121953:58:0;14265:354:1;121953:58:0;122024:31;122033:5;122040:7;122049:5;122024:8;:31::i;:::-;121624:439;;;121418:645;;;;;;;:::o;116248:219::-;116335:7;-1:-1:-1;;;;;116363:22:0;;116380:4;116363:22;116355:62;;;;-1:-1:-1;;;116355:62:0;;14826:2:1;116355:62:0;;;14808:21:1;14865:2;14845:18;;;14838:30;14904:29;14884:18;;;14877:57;14951:18;;116355:62:0;14624:351:1;116355:62:0;116947:7;116435:24;116866:234;105656:151;-1:-1:-1;;;;;105772:18:0;;;105745:7;105772:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;105656:151::o;125142:150::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;125258:21:0;;;;;;:12;:21;;;;;:26;;;;;;;;;;;;:::i;:::-;;;;;;;;;;125251:33;;;;;;;;;125258:26;;125251:33;;;;;;;;;-1:-1:-1;;;;;125251:33:0;;;;;;;;;125142:150;-1:-1:-1;;;125142:150:0:o;97462:201::-;96449:13;:11;:13::i;:::-;-1:-1:-1;;;;;97551:22:0;::::1;97543:73;;;::::0;-1:-1:-1;;;97543:73:0;;15182:2:1;97543:73:0::1;::::0;::::1;15164:21:1::0;15221:2;15201:18;;;15194:30;15260:34;15240:18;;;15233:62;-1:-1:-1;;;15311:18:1;;;15304:36;15357:19;;97543:73:0::1;14980:402:1::0;97543:73:0::1;97627:28;97646:8;97627:18;:28::i;80530:348::-:0;80626:11;80676:2;80660:5;80654:19;:24;80650:221;;;80702:20;80716:5;80702:13;:20::i;:::-;80695:27;;;;80650:221;80781:5;80755:46;80796:5;80781;80755:46;:::i;:::-;-1:-1:-1;78959:66:0;;-1:-1:-1;80816:43:0;;76717:207;76896:10;76717:207::o;130232:290::-;130317:28;130329:7;130338:6;130317:11;:28::i;:::-;104984:12;;-1:-1:-1;;;;;;130364:29:0;130356:90;;;;-1:-1:-1;;;130356:90:0;;17793:2:1;130356:90:0;;;17775:21:1;17832:2;17812:18;;;17805:30;17871:34;17851:18;;;17844:62;-1:-1:-1;;;17922:18:1;;;17915:46;17978:19;;130356:90:0;17591:412:1;130356:90:0;130459:55;130476:23;130501:4;130507:6;130459:16;:55::i;:::-;;;130232:290;;:::o;110318:548::-;-1:-1:-1;;;;;110402:21:0;;110394:65;;;;-1:-1:-1;;;110394:65:0;;18210:2:1;110394:65:0;;;18192:21:1;18249:2;18229:18;;;18222:30;18288:33;18268:18;;;18261:61;18339:18;;110394:65:0;18008:355:1;110394:65:0;110472:49;110501:1;110505:7;110514:6;110472:20;:49::i;:::-;110550:6;110534:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;110705:18:0;;:9;:18;;;;;;;;;;;:28;;;;;;110760:37;1461:25:1;;;110760:37:0;;1434:18:1;110760:37:0;;;;;;;110810:48;110838:1;110842:7;110851:6;110810:19;:48::i;133171:98::-;133229:7;133256:5;133260:1;133256;:5;:::i;5485:195::-;5542:7;-1:-1:-1;;;;;5570:26:0;;;5562:78;;;;-1:-1:-1;;;5562:78:0;;18570:2:1;5562:78:0;;;18552:21:1;18609:2;18589:18;;;18582:30;18648:34;18628:18;;;18621:62;-1:-1:-1;;;18699:18:1;;;18692:37;18746:19;;5562:78:0;18368:403:1;5562:78:0;-1:-1:-1;5666:5:0;5485:195::o;18321:190::-;18377:6;18413:16;18404:25;;;18396:76;;;;-1:-1:-1;;;18396:76:0;;18978:2:1;18396:76:0;;;18960:21:1;19017:2;18997:18;;;18990:30;19056:34;19036:18;;;19029:62;-1:-1:-1;;;19107:18:1;;;19100:36;19153:19;;18396:76:0;18776:402:1;139942:588:0;-1:-1:-1;;;;;140112:18:0;;140108:415;;140168:26;140191:2;140168:22;:26::i;:::-;140209:28;:26;:28::i;:::-;139942:588;;;:::o;140108:415::-;-1:-1:-1;;;;;140259:16:0;;140255:268;;140313:28;140336:4;140313:22;:28::i;140255:268::-;140442:28;140465:4;140442:22;:28::i;:::-;140485:26;140508:2;140485:22;:26::i;130957:228::-;-1:-1:-1;;;;;125717:19:0;;;125690:7;125717:19;;;:10;:19;;;;;;;;;;;;;;;131121:56;;125717:19;;;;;131170:6;131121:16;:56::i;17263:190::-;17319:6;17355:16;17346:25;;;17338:76;;;;-1:-1:-1;;;17338:76:0;;19385:2:1;17338:76:0;;;19367:21:1;19424:2;19404:18;;;19397:30;19463:34;19443:18;;;19436:62;-1:-1:-1;;;19514:18:1;;;19507:36;19560:19;;17338:76:0;19183:402:1;133277:103:0;133340:7;133367:5;133371:1;133367;:5;:::i;47311:114::-;47403:14;;47311:114::o;112312:346::-;-1:-1:-1;;;;;112414:19:0;;112406:68;;;;-1:-1:-1;;;112406:68:0;;19792:2:1;112406:68:0;;;19774:21:1;19831:2;19811:18;;;19804:30;19870:34;19850:18;;;19843:62;-1:-1:-1;;;19921:18:1;;;19914:34;19965:19;;112406:68:0;19590:400:1;112406:68:0;-1:-1:-1;;;;;112493:21:0;;112485:68;;;;-1:-1:-1;;;112485:68:0;;20197:2:1;112485:68:0;;;20179:21:1;20236:2;20216:18;;;20209:30;20275:34;20255:18;;;20248:62;-1:-1:-1;;;20326:18:1;;;20319:32;20368:19;;112485:68:0;19995:398:1;112485:68:0;-1:-1:-1;;;;;112566:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;112618:32;;1461:25:1;;;112618:32:0;;1434:18:1;112618:32:0;;;;;;;112312:346;;;:::o;112949:419::-;113050:24;113077:25;113087:5;113094:7;113077:9;:25::i;:::-;113050:52;;-1:-1:-1;;113117:16:0;:37;113113:248;;113199:6;113179:16;:26;;113171:68;;;;-1:-1:-1;;;113171:68:0;;20600:2:1;113171:68:0;;;20582:21:1;20639:2;20619:18;;;20612:30;20678:31;20658:18;;;20651:59;20727:18;;113171:68:0;20398:353:1;113171:68:0;113283:51;113292:5;113299:7;113327:6;113308:16;:25;113283:8;:51::i;109225:806::-;-1:-1:-1;;;;;109322:18:0;;109314:68;;;;-1:-1:-1;;;109314:68:0;;20958:2:1;109314:68:0;;;20940:21:1;20997:2;20977:18;;;20970:30;21036:34;21016:18;;;21009:62;-1:-1:-1;;;21087:18:1;;;21080:35;21132:19;;109314:68:0;20756:401:1;109314:68:0;-1:-1:-1;;;;;109401:16:0;;109393:64;;;;-1:-1:-1;;;109393:64:0;;21364:2:1;109393:64:0;;;21346:21:1;21403:2;21383:18;;;21376:30;21442:34;21422:18;;;21415:62;-1:-1:-1;;;21493:18:1;;;21486:33;21536:19;;109393:64:0;21162:399:1;109393:64:0;109470:38;109491:4;109497:2;109501:6;109470:20;:38::i;:::-;-1:-1:-1;;;;;109543:15:0;;109521:19;109543:15;;;;;;;;;;;109577:21;;;;109569:72;;;;-1:-1:-1;;;109569:72:0;;21768:2:1;109569:72:0;;;21750:21:1;21807:2;21787:18;;;21780:30;21846:34;21826:18;;;21819:62;-1:-1:-1;;;21897:18:1;;;21890:36;21943:19;;109569:72:0;21566:402:1;109569:72:0;-1:-1:-1;;;;;109677:15:0;;;:9;:15;;;;;;;;;;;109695:20;;;109677:38;;109895:13;;;;;;;;;;:23;;;;;;109947:26;;1461:25:1;;;109895:13:0;;109947:26;;1434:18:1;109947:26:0;;;;;;;109986:37;110006:4;110012:2;110016:6;109986:19;:37::i;85682:268::-;85735:7;85767:4;-1:-1:-1;;;;;85776:11:0;85759:28;;:63;;;;;85808:14;85791:13;:31;85759:63;85755:188;;;-1:-1:-1;85846:22:0;;85682:268::o;85755:188::-;85908:23;86050:81;;;83874:95;86050:81;;;23857:25:1;86073:11:0;23898:18:1;;;23891:34;;;;86086:14:0;23941:18:1;;;23934:34;86102:13:0;23984:18:1;;;23977:34;86125:4:0;24027:19:1;;;24020:61;86013:7:0;;23829:19:1;;86050:81:0;;;;;;;;;;;;86040:92;;;;;;86033:99;;85958:182;;127119:1934;128343:12;;127216:7;;;128343:12;128441:1;128432:10;;128428:249;;;128459:11;128482:17;128492:6;128482:9;:17::i;:::-;128473:26;;:6;:26;:::i;:::-;133614:25;133676:21;;;133743:4;133730:18;;128459:40;;-1:-1:-1;128556:9:0;;133726:28;;128518:35;;;:47;128514:152;;;128593:3;128586:10;;128514:152;;;128643:7;:3;128649:1;128643:7;:::i;:::-;128637:13;;128514:152;128444:233;128428:249;128702:4;128696:3;:10;128689:249;;;128723:11;128737:23;128750:3;128755:4;128737:12;:23::i;:::-;133614:25;133676:21;;;133743:4;133730:18;;128723:37;;-1:-1:-1;128817:9:0;;133726:28;;128779:35;;;:47;128775:152;;;128854:3;128847:10;;128775:152;;;128904:7;:3;128910:1;128904:7;:::i;:::-;128898:13;;128775:152;128708:230;128689:249;;;128982:9;;:52;;133614:25;133676:21;;;133743:4;133730:18;;133726:28;;-1:-1:-1;;133726:28:0;128998:36;;;;-1:-1:-1;;;;;128998:36:0;128982:52;;;128994:1;128982:52;-1:-1:-1;;;;;128975:59:0;;127119:1934;-1:-1:-1;;;;;;127119:1934:0:o;96728:132::-;96636:6;;-1:-1:-1;;;;;96636:6:0;92527:10;96792:23;96784:68;;;;-1:-1:-1;;;96784:68:0;;22175:2:1;96784:68:0;;;22157:21:1;;;22194:18;;;22187:30;22253:34;22233:18;;;22226:62;22305:18;;96784:68:0;21973:356:1;95195:120:0;94204:16;:14;:16::i;:::-;95254:7:::1;:15:::0;;-1:-1:-1;;;;95254:15:0::1;::::0;;95285:22:::1;92527:10:::0;95294:12:::1;95285:22;::::0;-1:-1:-1;;;;;2930:32:1;;;2912:51;;2900:2;2885:18;95285:22:0::1;;;;;;;95195:120::o:0;145432:155::-;145551:28;145563:7;145572:6;145551:11;:28::i;140538:1619::-;140627:4;140633:7;140674:1;140661:10;:14;140653:49;;;;-1:-1:-1;;;140653:49:0;;22536:2:1;140653:49:0;;;22518:21:1;22575:2;22555:18;;;22548:30;-1:-1:-1;;;22594:18:1;;;22587:52;22656:18;;140653:49:0;22334:346:1;140653:49:0;140735:23;:21;:23::i;:::-;140721:10;:37;;140713:79;;;;-1:-1:-1;;;140713:79:0;;22887:2:1;140713:79:0;;;22869:21:1;22926:2;22906:18;;;22899:30;22965:31;22945:18;;;22938:59;23014:18;;140713:79:0;22685:353:1;140713:79:0;141931:13;141947:40;:9;141976:10;141947:28;:40::i;:::-;142013:20;;141931:56;;-1:-1:-1;142004:29:0;;142000:150;;142058:5;142065:1;142050:17;;;;;;;142000:150;142108:4;142114:9;:16;;142131:5;142114:23;;;;;;;;:::i;:::-;;;;;;;;;142100:38;;;;;140538:1619;;;;;;:::o;131363:388::-;-1:-1:-1;;;;;125717:19:0;;;131448:23;125717:19;;;:10;:19;;;;;;;;;;105168:18;;;;;;;131563:21;;;;:33;;;-1:-1:-1;;;;;;131563:33:0;;;;;;;131614:54;;125717:19;;;;;105168:18;;131563:33;;125717:19;;;131614:54;;131448:23;131614:54;131681:62;131698:15;131715:9;131726:16;131681;:62::i;145279:145::-;145393:23;145405:2;145409:6;145393:11;:23::i;97823:191::-;97916:6;;;-1:-1:-1;;;;;97933:17:0;;;-1:-1:-1;;;;;;97933:17:0;;;;;;;97966:40;;97916:6;;;97933:17;97916:6;;97966:40;;97897:16;;97966:40;97886:128;97823:191;:::o;94936:118::-;93945:19;:17;:19::i;:::-;94996:7:::1;:14:::0;;-1:-1:-1;;;;94996:14:0::1;-1:-1:-1::0;;;94996:14:0::1;::::0;;95026:20:::1;95033:12;92527:10:::0;;92447:98;81014:274;81108:13;78959:66;81138:47;;81134:147;;81209:15;81218:5;81209:8;:15::i;81134:147::-;81264:5;81257:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;138593:223;138640:7;138660:30;:18;47522:19;;47540:1;47522:19;;;47433:127;138660:30;138703:17;138723:23;:21;:23::i;:::-;138703:43;;138762:19;138771:9;138762:19;;;;1461:25:1;;1449:2;1434:18;;1315:177;138762:19:0;;;;;;;;138799:9;138593:223;-1:-1:-1;138593:223:0:o;86782:167::-;86859:7;86886:55;86908:20;:18;:20::i;:::-;86930:10;72648:4;72642:11;-1:-1:-1;;;72667:23:0;;72720:4;72711:14;;72704:39;;;;72773:4;72764:14;;72757:34;72828:4;72813:20;;;72445:406;70661:236;70746:7;70767:17;70786:18;70808:25;70819:4;70825:1;70828;70831;70808:10;:25::i;:::-;70766:67;;;;70844:18;70856:5;70844:11;:18::i;:::-;-1:-1:-1;70880:9:0;70661:236;-1:-1:-1;;;;;70661:236:0:o;122640:207::-;-1:-1:-1;;;;;122761:14:0;;122700:15;122761:14;;;:7;:14;;;;;47403;;47540:1;47522:19;;;;47403:14;122822:17;122717:130;122640:207;;;:::o;79287:292::-;79352:11;79376:17;79402:3;79376:30;;79435:2;79421:4;:11;:16;79417:74;;;79475:3;79461:18;;-1:-1:-1;;;79461:18:0;;;;;;;;:::i;79417:74::-;79558:11;;79541:13;79558:4;79541:13;:::i;:::-;79533:36;;79287:292;-1:-1:-1;;;79287:292:0:o;132376:787::-;132613:12;;132550:17;;;;;132691:8;;:59;;133614:25;133676:21;;;133743:4;133730:18;;133726:28;;-1:-1:-1;;133726:28:0;132691:59;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;132691:59:0;;;;;;;;132702:16;;;;;;;;;-1:-1:-1;132702:16:0;;;;;;;132691:59;132663:87;;132779:7;:13;;;-1:-1:-1;;;;;132767:25:0;;;132819:20;132822:9;132833:5;132819:2;:20;;:::i;:::-;132807:32;;132866:1;132860:3;:7;:39;;;;;132892:7;:5;:7::i;:::-;132871:28;;:7;:17;;;:28;;;132860:39;132856:289;;;132958:29;132977:9;132958:18;:29::i;:::-;133614:25;133676:21;;;133743:4;133730:18;;133726:28;;-1:-1:-1;;133726:28:0;132920:67;;-1:-1:-1;;;;;132920:67:0;;;;;;;;;;;;;;;;132856:289;;;133028:5;133039:89;;;;;;;;133062:26;133080:7;:5;:7::i;:::-;133062:26;;:17;:26::i;:::-;133039:89;;;;;;133097:29;133116:9;133097:18;:29::i;:::-;-1:-1:-1;;;;;133039:89:0;;;;;;133028:101;;;;;;;-1:-1:-1;133028:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132856:289;132638:518;132588:575;132376:787;;;;;;:::o;144779:221::-;93945:19;:17;:19::i;:::-;144948:44:::1;144975:4;144981:2;144985:6;144948:26;:44::i;145078:193::-:0;145220:43;145246:4;145252:2;145256:6;145220:25;:43::i;142165:146::-;-1:-1:-1;;;;;142249:33:0;;;;;;:24;:33;;;;;;;;105168:18;;;;;;;;142233:70;;142249:33;142233:15;:70::i;142284:18::-;142233:15;:70::i;142319:118::-;142376:53;142392:21;142415:13;104984:12;;;104896:108;131759:609;131857:3;-1:-1:-1;;;;;131850:10:0;:3;-1:-1:-1;;;;;131850:10:0;;;:24;;;;;131873:1;131864:6;:10;131850:24;131846:515;;;-1:-1:-1;;;;;131895:17:0;;;131891:224;;-1:-1:-1;;;;;131991:17:0;;131934;131991;;;:12;:17;;;;;131934;;131974:54;;132010:9;132021:6;131974:16;:54::i;:::-;131933:95;;;;132073:3;-1:-1:-1;;;;;132052:47:0;;132078:9;132089;132052:47;;;;;;23519:25:1;;;23575:2;23560:18;;23553:34;23507:2;23492:18;;23345:248;132052:47:0;;;;;;;;131914:201;;131891:224;-1:-1:-1;;;;;132135:17:0;;;132131:219;;-1:-1:-1;;;;;132231:17:0;;132174;132231;;;:12;:17;;;;;132174;;132214:49;;132250:4;132256:6;132214:16;:49::i;:::-;132173:90;;;;132308:3;-1:-1:-1;;;;;132287:47:0;;132313:9;132324;132287:47;;;;;;23519:25:1;;;23575:2;23560:18;;23553:34;23507:2;23492:18;;23345:248;132287:47:0;;;;;;;;132154:196;;131759:609;;;:::o;54616:1673::-;54664:7;54688:1;54693;54688:6;54684:47;;-1:-1:-1;54718:1:0;;54616:1673;-1:-1:-1;54616:1673:0:o;54684:47::-;55422:14;55456:1;55445:7;55450:1;55445:4;:7::i;:::-;:12;;55439:1;:19;;55422:36;;55924:1;55913:6;55909:1;:10;;;;;:::i;:::-;;55900:6;:19;55899:26;;55890:35;;55974:1;55963:6;55959:1;:10;;;;;:::i;:::-;;55950:6;:19;55949:26;;55940:35;;56024:1;56013:6;56009:1;:10;;;;;:::i;:::-;;56000:6;:19;55999:26;;55990:35;;56074:1;56063:6;56059:1;:10;;;;;:::i;:::-;;56050:6;:19;56049:26;;56040:35;;56124:1;56113:6;56109:1;:10;;;;;:::i;:::-;;56100:6;:19;56099:26;;56090:35;;56174:1;56163:6;56159:1;:10;;;;;:::i;:::-;;56150:6;:19;56149:26;;56140:35;;56224:1;56213:6;56209:1;:10;;;;;:::i;:::-;;56200:6;:19;56199:26;;56190:35;;56247:23;56251:6;56263;56259:1;:10;;;;;:::i;:::-;;56247:3;:23::i;48773:156::-;48835:7;48910:11;48920:1;48911:5;;;48910:11;:::i;:::-;48900:21;;48901:5;;;48900:21;:::i;94684:108::-;94411:7;;-1:-1:-1;;;94411:7:0;;;;94743:41;;;;-1:-1:-1;;;94743:41:0;;24648:2:1;94743:41:0;;;24630:21:1;24687:2;24667:18;;;24660:30;-1:-1:-1;;;24706:18:1;;;24699:50;24766:18;;94743:41:0;24446:344:1;130616:194:0;130701:28;130713:7;130722:6;130701:11;:28::i;:::-;130742:60;130759:23;130784:9;130795:6;130742:16;:60::i;138882:127::-;138946:7;138973:28;:18;47403:14;;47311:114;88418:958;88531:12;;88507:7;;88531:17;;88527:58;;-1:-1:-1;88572:1:0;88565:8;;88527:58;88638:12;;88597:11;;88663:444;88676:4;88670:3;:10;88663:444;;;88697:11;88711:23;88724:3;88729:4;88711:12;:23::i;:::-;91252:31;91629:19;;;91687:4;91674:18;;88697:37;;-1:-1:-1;88988:7:0;;91670:28;;88955:30;:40;88951:145;;;89023:3;89016:10;;88951:145;;;89073:7;:3;89079:1;89073:7;:::i;:::-;89067:13;;88951:145;88682:425;88663:444;;;89233:1;89227:3;:7;:56;;;;-1:-1:-1;89276:7:0;89238:28;89251:5;89258:7;89264:1;89258:3;:7;:::i;:::-;91252:31;91629:19;;;91687:4;91674:18;;;91670:28;;91171:584;89238:28;:34;:45;89227:56;89223:146;;;89307:7;89313:1;89307:3;:7;:::i;:::-;89300:14;;;;;;89223:146;-1:-1:-1;89354:3:0;-1:-1:-1;89347:10:0;;94499:108;94411:7;;-1:-1:-1;;;94411:7:0;;;;94569:9;94561:38;;;;-1:-1:-1;;;94561:38:0;;24997:2:1;94561:38:0;;;24979:21:1;25036:2;25016:18;;;25009:30;-1:-1:-1;;;25055:18:1;;;25048:46;25111:18;;94561:38:0;24795:340:1;79668:415:0;79727:13;79753:11;79767:16;79778:4;79767:10;:16::i;:::-;79893:14;;;79904:2;79893:14;;;;;;;;;79753:30;;-1:-1:-1;79873:17:0;;79893:14;;;;;;;;;-1:-1:-1;;;79986:16:0;;;-1:-1:-1;80032:4:0;80023:14;;80016:28;;;;-1:-1:-1;79986:16:0;79668:415::o;69045:1477::-;69133:7;;70067:66;70054:79;;70050:163;;;-1:-1:-1;70166:1:0;;-1:-1:-1;70170:30:0;70150:51;;70050:163;70327:24;;;70310:14;70327:24;;;;;;;;;25367:25:1;;;25440:4;25428:17;;25408:18;;;25401:45;;;;25462:18;;;25455:34;;;25505:18;;;25498:34;;;70327:24:0;;25339:19:1;;70327:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;70327:24:0;;-1:-1:-1;;70327:24:0;;;-1:-1:-1;;;;;;;70366:20:0;;70362:103;;70419:1;70423:29;70403:50;;;;;;;70362:103;70485:6;-1:-1:-1;70493:20:0;;-1:-1:-1;69045:1477:0;;;;;;;;:::o;64505:521::-;64583:20;64574:5;:29;;;;;;;;:::i;:::-;;64570:449;;64505:521;:::o;64570:449::-;64681:29;64672:5;:38;;;;;;;;:::i;:::-;;64668:351;;64727:34;;-1:-1:-1;;;64727:34:0;;25877:2:1;64727:34:0;;;25859:21:1;25916:2;25896:18;;;25889:30;25955:26;25935:18;;;25928:54;25999:18;;64727:34:0;25675:348:1;64668:351:0;64792:35;64783:5;:44;;;;;;;;:::i;:::-;;64779:240;;64844:41;;-1:-1:-1;;;64844:41:0;;26230:2:1;64844:41:0;;;26212:21:1;26269:2;26249:18;;;26242:30;26308:33;26288:18;;;26281:61;26359:18;;64844:41:0;26028:355:1;64779:240:0;64916:30;64907:5;:39;;;;;;;;:::i;:::-;;64903:116;;64963:44;;-1:-1:-1;;;64963:44:0;;26590:2:1;64963:44:0;;;26572:21:1;26629:2;26609:18;;;26602:30;26668:34;26648:18;;;26641:62;-1:-1:-1;;;26719:18:1;;;26712:32;26761:19;;64963:44:0;26388:398:1;142445:310:0;142540:17;142560:23;:21;:23::i;:::-;142540:43;-1:-1:-1;142540:43:0;142598:30;142614:9;142598:15;:30::i;:::-;:42;142594:154;;;142657:29;;;;;;;;-1:-1:-1;142657:29:0;;;;;;;;;;;;;;142701:16;;;:35;;;;;;;;;;;;;;;142445:310::o;56766:1019::-;56818:7;;56905:3;56896:12;;;:16;56892:102;;56943:3;56933:13;;;;56965;56892:102;57021:2;57012:11;;;:15;57008:99;;57058:2;57048:12;;;;57079;57008:99;57134:2;57125:11;;;:15;57121:99;;57171:2;57161:12;;;;57192;57121:99;57247:2;57238:11;;;:15;57234:99;;57284:2;57274:12;;;;57305;57234:99;57360:1;57351:10;;;:14;57347:96;;57396:1;57386:11;;;;57416;57347:96;57470:1;57461:10;;;:14;57457:96;;57506:1;57496:11;;;;57526;57457:96;57580:1;57571:10;;;:14;57567:96;;57616:1;57606:11;;;;57636;57567:96;57690:1;57681:10;;;:14;57677:66;;57726:1;57716:11;57771:6;56766:1019;-1:-1:-1;;56766:1019:0:o;48548:106::-;48606:7;48637:1;48633;:5;:13;;48645:1;48633:13;;;-1:-1:-1;48641:1:0;;48548:106;-1:-1:-1;48548:106:0:o;111199:675::-;-1:-1:-1;;;;;111283:21:0;;111275:67;;;;-1:-1:-1;;;111275:67:0;;26993:2:1;111275:67:0;;;26975:21:1;27032:2;27012:18;;;27005:30;27071:34;27051:18;;;27044:62;-1:-1:-1;;;27122:18:1;;;27115:31;27163:19;;111275:67:0;26791:397:1;111275:67:0;111355:49;111376:7;111393:1;111397:6;111355:20;:49::i;:::-;-1:-1:-1;;;;;111442:18:0;;111417:22;111442:18;;;;;;;;;;;111479:24;;;;111471:71;;;;-1:-1:-1;;;111471:71:0;;27395:2:1;111471:71:0;;;27377:21:1;27434:2;27414:18;;;27407:30;27473:34;27453:18;;;27446:62;-1:-1:-1;;;27524:18:1;;;27517:32;27566:19;;111471:71:0;27193:398:1;111471:71:0;-1:-1:-1;;;;;111578:18:0;;:9;:18;;;;;;;;;;;111599:23;;;111578:44;;111717:12;:22;;;;;;;111768:37;1461:25:1;;;111578:9:0;;:18;111768:37;;1434:18:1;111768:37:0;;;;;;;111818:48;111838:7;111855:1;111859:6;111818:19;:48::i;80160:251::-;80221:7;80294:4;80258:40;;80322:2;80313:11;;80309:71;;;80348:20;;-1:-1:-1;;;80348:20:0;;;;;;;;;;;142763:212;142857:10;;142833:7;;142857:15;;142853:115;;-1:-1:-1;142896:1:0;;142763:212;-1:-1:-1;142763:212:0:o;142853:115::-;142941:10;;142937:3;;142941:14;;142954:1;;142941:14;:::i;:::-;142937:19;;;;;;;;:::i;:::-;;;;;;;;;142930:26;;142763:212;;;:::o;142853:115::-;142763:212;;;:::o;14:423: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;;;160:3;363:1;356:4;347:6;342:3;338:16;334:27;327:38;426:4;419:2;415:7;410:2;402:6;398:15;394:29;389:3;385:39;381:50;374:57;;;14:423;;;;:::o;442:220::-;591:2;580:9;573:21;554:4;611:45;652:2;641:9;637:18;629:6;611:45;:::i;667:131::-;-1:-1:-1;;;;;742:31:1;;732:42;;722:70;;788:1;785;778:12;803:315;871:6;879;932:2;920:9;911:7;907:23;903:32;900:52;;;948:1;945;938:12;900:52;987:9;974:23;1006:31;1031:5;1006:31;:::i;:::-;1056:5;1108:2;1093:18;;;;1080:32;;-1:-1:-1;;;803:315:1:o;1497:456::-;1574:6;1582;1590;1643:2;1631:9;1622:7;1618:23;1614:32;1611:52;;;1659:1;1656;1649:12;1611:52;1698:9;1685:23;1717:31;1742:5;1717:31;:::i;:::-;1767:5;-1:-1:-1;1824:2:1;1809:18;;1796:32;1837:33;1796:32;1837:33;:::i;:::-;1497:456;;1889:7;;-1:-1:-1;;;1943:2:1;1928:18;;;;1915:32;;1497:456::o;2329:180::-;2388:6;2441:2;2429:9;2420:7;2416:23;2412:32;2409:52;;;2457:1;2454;2447:12;2409:52;-1:-1:-1;2480:23:1;;2329:180;-1:-1:-1;2329:180:1:o;2514:247::-;2573:6;2626:2;2614:9;2605:7;2601:23;2597:32;2594:52;;;2642:1;2639;2632:12;2594:52;2681:9;2668:23;2700:31;2725:5;2700:31;:::i;2974:964::-;3099:6;3107;3115;3123;3131;3184:3;3172:9;3163:7;3159:23;3155:33;3152:53;;;3201:1;3198;3191:12;3152:53;3240:9;3227:23;3259:31;3284:5;3259:31;:::i;:::-;3309:5;-1:-1:-1;3366:2:1;3351:18;;3338:32;3379:33;3338:32;3379:33;:::i;:::-;3431:7;-1:-1:-1;3485:2:1;3470:18;;3457:32;;-1:-1:-1;3540:2:1;3525:18;;3512:32;3563:18;3593:14;;;3590:34;;;3620:1;3617;3610:12;3590:34;3658:6;3647:9;3643:22;3633:32;;3703:7;3696:4;3692:2;3688:13;3684:27;3674:55;;3725:1;3722;3715:12;3674:55;3765:2;3752:16;3791:2;3783:6;3780:14;3777:34;;;3807:1;3804;3797:12;3777:34;3852:7;3847:2;3838:6;3834:2;3830:15;3826:24;3823:37;3820:57;;;3873:1;3870;3863:12;3820:57;2974:964;;;;-1:-1:-1;2974:964:1;;-1:-1:-1;3904:2:1;3896:11;;3926:6;2974:964;-1:-1:-1;;;2974:964:1:o;4140:1259::-;4546:3;4541;4537:13;4529:6;4525:26;4514:9;4507:45;4488:4;4571:2;4609:3;4604:2;4593:9;4589:18;4582:31;4636:46;4677:3;4666:9;4662:19;4654:6;4636:46;:::i;:::-;4730:9;4722:6;4718:22;4713:2;4702:9;4698:18;4691:50;4764:33;4790:6;4782;4764:33;:::i;:::-;4828:2;4813:18;;4806:34;;;-1:-1:-1;;;;;4877:32:1;;4871:3;4856:19;;4849:61;4897:3;4926:19;;4919:35;;;4991:22;;;4985:3;4970:19;;4963:51;5063:13;;5085:22;;;5161:15;;;;-1:-1:-1;5123:15:1;;;;-1:-1:-1;5204:169:1;5218:6;5215:1;5212:13;5204:169;;;5279:13;;5267:26;;5348:15;;;;5313:12;;;;5240:1;5233:9;5204:169;;;-1:-1:-1;5390:3:1;;4140:1259;-1:-1:-1;;;;;;;;;;;;4140:1259:1:o;5605:156::-;5671:20;;5731:4;5720:16;;5710:27;;5700:55;;5751:1;5748;5741:12;5766:592;5868:6;5876;5884;5892;5900;5908;5961:3;5949:9;5940:7;5936:23;5932:33;5929:53;;;5978:1;5975;5968:12;5929:53;6017:9;6004:23;6036:31;6061:5;6036:31;:::i;:::-;6086:5;-1:-1:-1;6138:2:1;6123:18;;6110:32;;-1:-1:-1;6189:2:1;6174:18;;6161:32;;-1:-1:-1;6212:36:1;6244:2;6229:18;;6212:36;:::i;:::-;6202:46;;6295:3;6284:9;6280:19;6267:33;6257:43;;6347:3;6336:9;6332:19;6319:33;6309:43;;5766:592;;;;;;;;:::o;6363:734::-;6474:6;6482;6490;6498;6506;6514;6522;6575:3;6563:9;6554:7;6550:23;6546:33;6543:53;;;6592:1;6589;6582:12;6543:53;6631:9;6618:23;6650:31;6675:5;6650:31;:::i;:::-;6700:5;-1:-1:-1;6757:2:1;6742:18;;6729:32;6770:33;6729:32;6770:33;:::i;:::-;6822:7;-1:-1:-1;6876:2:1;6861:18;;6848:32;;-1:-1:-1;6927:2:1;6912:18;;6899:32;;-1:-1:-1;6950:37:1;6982:3;6967:19;;6950:37;:::i;:::-;6940:47;;7034:3;7023:9;7019:19;7006:33;6996:43;;7086:3;7075:9;7071:19;7058:33;7048:43;;6363:734;;;;;;;;;;:::o;7102:388::-;7170:6;7178;7231:2;7219:9;7210:7;7206:23;7202:32;7199:52;;;7247:1;7244;7237:12;7199:52;7286:9;7273:23;7305:31;7330:5;7305:31;:::i;:::-;7355:5;-1:-1:-1;7412:2:1;7397:18;;7384:32;7425:33;7384:32;7425:33;:::i;:::-;7477:7;7467:17;;;7102:388;;;;;:::o;7495:419::-;7562:6;7570;7623:2;7611:9;7602:7;7598:23;7594:32;7591:52;;;7639:1;7636;7629:12;7591:52;7678:9;7665:23;7697:31;7722:5;7697:31;:::i;:::-;7747:5;-1:-1:-1;7804:2:1;7789:18;;7776:32;7852:10;7839:24;;7827:37;;7817:65;;7878:1;7875;7868:12;8270:380;8349:1;8345:12;;;;8392;;;8413:61;;8467:4;8459:6;8455:17;8445:27;;8413:61;8520:2;8512:6;8509:14;8489:18;8486:38;8483:161;;8566:10;8561:3;8557:20;8554:1;8547:31;8601:4;8598:1;8591:15;8629:4;8626:1;8619:15;8655:127;8716:10;8711:3;8707:20;8704:1;8697:31;8747:4;8744:1;8737:15;8771:4;8768:1;8761:15;8787:125;8852:9;;;8873:10;;;8870:36;;;8886:18;;:::i;10041:734::-;-1:-1:-1;;;;;10348:15:1;;;10330:34;;10400:15;;10395:2;10380:18;;10373:43;10447:2;10432:18;;10425:34;;;10490:2;10475:18;;10468:34;;;10310:3;10533;10518:19;;10511:32;;;10559:19;;10552:35;;;10273:4;10580:6;10630;10624:3;10609:19;;10596:49;10695:1;10689:3;10680:6;10669:9;10665:22;10661:32;10654:43;10765:3;10758:2;10754:7;10749:2;10741:6;10737:15;10733:29;10722:9;10718:45;10714:55;10706:63;;10041:734;;;;;;;;;:::o;10780:184::-;10850:6;10903:2;10891:9;10882:7;10878:23;10874:32;10871:52;;;10919:1;10916;10909:12;10871:52;-1:-1:-1;10942:16:1;;10780:184;-1:-1:-1;10780:184:1:o;11374:128::-;11441:9;;;11462:11;;;11459:37;;;11476:18;;:::i;11507:127::-;11568:10;11563:3;11559:20;11556:1;11549:31;11599:4;11596:1;11589:15;11623:4;11620:1;11613:15;11639:127;11700:10;11695:3;11691:20;11688:1;11681:31;11731:4;11728:1;11721:15;11755:4;11752:1;11745:15;15513:545;15615:2;15610:3;15607:11;15604:448;;;15651:1;15676:5;15672:2;15665:17;15721:4;15717:2;15707:19;15791:2;15779:10;15775:19;15772:1;15768:27;15762:4;15758:38;15827:4;15815:10;15812:20;15809:47;;;-1:-1:-1;15850:4:1;15809:47;15905:2;15900:3;15896:12;15893:1;15889:20;15883:4;15879:31;15869:41;;15960:82;15978:2;15971:5;15968:13;15960:82;;;16023:17;;;16004:1;15993:13;15960:82;;;15964:3;;;15513:545;;;:::o;16234:1352::-;16360:3;16354:10;16387:18;16379:6;16376:30;16373:56;;;16409:18;;:::i;:::-;16438:97;16528:6;16488:38;16520:4;16514:11;16488:38;:::i;:::-;16482:4;16438:97;:::i;:::-;16590:4;;16654:2;16643:14;;16671:1;16666:663;;;;17373:1;17390:6;17387:89;;;-1:-1:-1;17442:19:1;;;17436:26;17387:89;-1:-1:-1;;16191:1:1;16187:11;;;16183:24;16179:29;16169:40;16215:1;16211:11;;;16166:57;17489:81;;16636:944;;16666:663;15460:1;15453:14;;;15497:4;15484:18;;-1:-1:-1;;16702:20:1;;;16820:236;16834:7;16831:1;16828:14;16820:236;;;16923:19;;;16917:26;16902:42;;17015:27;;;;16983:1;16971:14;;;;16850:19;;16820:236;;;16824:3;17084:6;17075:7;17072:19;17069:201;;;17145:19;;;17139:26;-1:-1:-1;;17228:1:1;17224:14;;;17240:3;17220:24;17216:37;17212:42;17197:58;17182:74;;17069:201;-1:-1:-1;;;;;17316:1:1;17300:14;;;17296:22;17283:36;;-1:-1:-1;16234:1352:1:o;23043:297::-;23161:12;;23208:4;23197:16;;;23191:23;;23161:12;23226:16;;23223:111;;;-1:-1:-1;;23300:4:1;23296:17;;;;23293:1;23289:25;23285:38;23274:50;;23043:297;-1:-1:-1;23043:297:1:o;24092:127::-;24153:10;24148:3;24144:20;24141:1;24134:31;24184:4;24181:1;24174:15;24208:4;24205:1;24198:15;24224:217;24264:1;24290;24280:132;;24334:10;24329:3;24325:20;24322:1;24315:31;24369:4;24366:1;24359:15;24397:4;24394:1;24387:15;24280:132;-1:-1:-1;24426:9:1;;24224:217::o;25543:127::-;25604:10;25599:3;25595:20;25592:1;25585:31;25635:4;25632:1;25625:15;25659:4;25656:1;25649:15

Swarm Source

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