ETH Price: $3,246.22 (-0.38%)
Gas: 2 Gwei

Token

Real Strawberry Elephant (صباح فراوله)
 

Overview

Max Total Supply

100,000,000,000 صباح فراوله

Holders

102

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

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

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

Contract Source Code Verified (Exact Match)

Contract Name:
RealStrawberryElephant

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-09-15
*/

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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


// OpenZeppelin Contracts (last updated v4.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/contracts/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/contracts/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/contracts/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/contracts/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/contracts/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/contracts/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/contracts/utils/Context.sol


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

pragma solidity ^0.8.0;

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

// File: @openzeppelin/contracts/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/contracts/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/contracts/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/contracts/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/contracts/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/contracts/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-437ac0324e.sol


pragma solidity ^0.8.9;









contract RealStrawberryElephant is ERC20, ERC20Burnable, ERC20Snapshot, Ownable, Pausable, ERC20Permit, ERC20Votes, ERC20FlashMint {
    constructor()
        ERC20("Real Strawberry Elephant", unicode"صباح فراوله")
        ERC20Permit("Real Strawberry Elephant")
    {
        _mint(msg.sender, 100000000000 * 10 ** decimals());
    }

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

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

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

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

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

    // The following functions are overrides required by Solidity.

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

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

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Snapshot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32","name":"pos","type":"uint32"}],"name":"checkpoints","outputs":[{"components":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint224","name":"votes","type":"uint224"}],"internalType":"struct ERC20Votes.Checkpoint","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"flashFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC3156FlashBorrower","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"maxFlashLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"snapshot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101606040523480156200001257600080fd5b506040518060400160405280601881526020017f5265616c205374726177626572727920456c657068616e740000000000000000815250806040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280601881526020017f5265616c205374726177626572727920456c657068616e7400000000000000008152506040518060400160405280601581526020017fd8b5d8a8d8a7d8ad20d981d8b1d8a7d988d984d98700000000000000000000008152508160039081620000fd919062001457565b5080600490816200010f919062001457565b50505062000132620001266200024f60201b60201c565b6200025760201b60201c565b6000600960146101000a81548160ff02191690831515021790555062000168600a836200031d60201b6200183a1790919060201c565b61012081815250506200018b600b826200031d60201b6200183a1790919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a08181525050620001ca6200037a60201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff168152505050505062000249336200021d620003d760201b60201c565b600a6200022b9190620016ce565b64174876e8006200023d91906200171f565b620003e060201b60201c565b62001dc0565b600033905090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600060208351101562000343576200033b83620003fb60201b60201c565b905062000374565b826200035a836200046860201b6200187e1760201c565b60000190816200036b919062001457565b5060ff60001b90505b92915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e051610100514630604051602001620003bc959493929190620017db565b60405160208183030381529060405280519060200120905090565b60006012905090565b620003f782826200047260201b620018881760201c565b5050565b600080829050601f815111156200044b57826040517f305a27a9000000000000000000000000000000000000000000000000000000008152600401620004429190620018c7565b60405180910390fd5b80518162000459906200191d565b60001c1760001b915050919050565b6000819050919050565b6200048982826200053060201b620019151760201c565b620004996200069d60201b60201c565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16620004c7620006c160201b60201c565b11156200050b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005029062001a03565b60405180910390fd5b6200052a6010620006cb60201b62001a6b1783620006e360201b60201c565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620005a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005999062001a75565b60405180910390fd5b620005b66000838362000a0860201b60201c565b8060026000828254620005ca919062001a97565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516200067d919062001ad2565b60405180910390a3620006996000838362000a3560201b60201c565b5050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b6000600254905090565b60008183620006db919062001a97565b905092915050565b6000806000858054905090506000808214620007b3576200070e876001840362000a5260201b60201c565b6040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050620007ef565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152505b905080602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1693506200082284868860201c565b92506000821180156200085557506200084062000a6760201b60201c565b65ffffffffffff16816000015163ffffffff16145b15620008dd57620008718362000a8460201b62001a811760201c565b62000886886001850362000a5260201b60201c565b60000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550620009fe565b86604051806040016040528062000916620008fd62000a6760201b60201c565b65ffffffffffff1662000af260201b62001aec1760201c565b63ffffffff168152602001620009378662000a8460201b62001a811760201c565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555050505b5050935093915050565b62000a1862000b4860201b60201c565b62000a3083838362000b9d60201b62001b3f1760201c565b505050565b62000a4d83838362000c9660201b62001bf71760201c565b505050565b60008260005281602060002001905092915050565b600062000a7f4362000ce660201b62001c221760201c565b905090565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff801682111562000aea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000ae19062001b65565b60405180910390fd5b819050919050565b600063ffffffff801682111562000b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000b379062001bfd565b60405180910390fd5b819050919050565b62000b5862000d3e60201b60201c565b1562000b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000b929062001c6f565b60405180910390fd5b565b62000bb583838362000d5560201b62001c771760201c565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000c115762000bfb8262000d5a60201b60201c565b62000c0b62000dbd60201b60201c565b62000c91565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000c6d5762000c578362000d5a60201b60201c565b62000c6762000dbd60201b60201c565b62000c90565b62000c7e8362000d5a60201b60201c565b62000c8f8262000d5a60201b60201c565b5b5b505050565b62000cae83838362000de160201b62001c7c1760201c565b62000ce162000cc38462000de660201b60201c565b62000cd48462000de660201b60201c565b8362000e4f60201b60201c565b505050565b600065ffffffffffff801682111562000d36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000d2d9062001d07565b60405180910390fd5b819050919050565b6000600960149054906101000a900460ff16905090565b505050565b62000dba600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002062000dae836200107260201b60201c565b620010ba60201b60201c565b50565b62000ddf600662000dd3620006c160201b60201c565b620010ba60201b60201c565b565b505050565b6000600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801562000e8c5750600081115b156200106d57600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161462000f7f5760008062000f26600f60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206200114660201b62001c811785620006e360201b60201c565b915091508473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405162000f7492919062001d29565b60405180910390a250505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146200106c5760008062001013600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020620006cb60201b62001a6b1785620006e360201b60201c565b915091508373ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516200106192919062001d29565b60405180910390a250505b5b505050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000620010cc6200115e60201b60201c565b905080620010e3846000016200117c60201b60201c565b1015620011415782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b6000818362001156919062001d56565b905092915050565b6000620011776008620011cf60201b62001c971760201c565b905090565b600080828054905003620011945760009050620011ca565b8160018380549050620011a8919062001d56565b81548110620011bc57620011bb62001d91565b5b906000526020600020015490505b919050565b600081600001549050919050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200125f57607f821691505b60208210810362001275576200127462001217565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620012df7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620012a0565b620012eb8683620012a0565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062001338620013326200132c8462001303565b6200130d565b62001303565b9050919050565b6000819050919050565b620013548362001317565b6200136c62001363826200133f565b848454620012ad565b825550505050565b600090565b6200138362001374565b6200139081848462001349565b505050565b5b81811015620013b857620013ac60008262001379565b60018101905062001396565b5050565b601f8211156200140757620013d1816200127b565b620013dc8462001290565b81016020851015620013ec578190505b62001404620013fb8562001290565b83018262001395565b50505b505050565b600082821c905092915050565b60006200142c600019846008026200140c565b1980831691505092915050565b600062001447838362001419565b9150826002028217905092915050565b6200146282620011dd565b67ffffffffffffffff8111156200147e576200147d620011e8565b5b6200148a825462001246565b62001497828285620013bc565b600060209050601f831160018114620014cf5760008415620014ba578287015190505b620014c6858262001439565b86555062001536565b601f198416620014df866200127b565b60005b828110156200150957848901518255600182019150602085019450602081019050620014e2565b8683101562001529578489015162001525601f89168262001419565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b6001851115620015cc57808604811115620015a457620015a36200153e565b5b6001851615620015b45780820291505b8081029050620015c4856200156d565b945062001584565b94509492505050565b600082620015e75760019050620016ba565b81620015f75760009050620016ba565b81600181146200161057600281146200161b5762001651565b6001915050620016ba565b60ff84111562001630576200162f6200153e565b5b8360020a9150848211156200164a57620016496200153e565b5b50620016ba565b5060208310610133831016604e8410600b84101617156200168b5782820a9050838111156200168557620016846200153e565b5b620016ba565b6200169a84848460016200157a565b92509050818404811115620016b457620016b36200153e565b5b81810290505b9392505050565b600060ff82169050919050565b6000620016db8262001303565b9150620016e883620016c1565b9250620017177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484620015d5565b905092915050565b60006200172c8262001303565b9150620017398362001303565b9250828202620017498162001303565b915082820484148315176200176357620017626200153e565b5b5092915050565b6000819050919050565b6200177f816200176a565b82525050565b620017908162001303565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620017c38262001796565b9050919050565b620017d581620017b6565b82525050565b600060a082019050620017f2600083018862001774565b62001801602083018762001774565b62001810604083018662001774565b6200181f606083018562001785565b6200182e6080830184620017ca565b9695505050505050565b600082825260208201905092915050565b60005b83811015620018695780820151818401526020810190506200184c565b60008484015250505050565b6000601f19601f8301169050919050565b60006200189382620011dd565b6200189f818562001838565b9350620018b181856020860162001849565b620018bc8162001875565b840191505092915050565b60006020820190508181036000830152620018e3818462001886565b905092915050565b600081519050919050565b6000819050602082019050919050565b60006200191482516200176a565b80915050919050565b60006200192a82620018eb565b826200193684620018f6565b9050620019438162001906565b925060208210156200198657620019817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802620012a0565b831692505b5050919050565b7f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60008201527f766572666c6f77696e6720766f74657300000000000000000000000000000000602082015250565b6000620019eb60308362001838565b9150620019f8826200198d565b604082019050919050565b6000602082019050818103600083015262001a1e81620019dc565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b600062001a5d601f8362001838565b915062001a6a8262001a25565b602082019050919050565b6000602082019050818103600083015262001a908162001a4e565b9050919050565b600062001aa48262001303565b915062001ab18362001303565b925082820190508082111562001acc5762001acb6200153e565b5b92915050565b600060208201905062001ae9600083018462001785565b92915050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203260008201527f3234206269747300000000000000000000000000000000000000000000000000602082015250565b600062001b4d60278362001838565b915062001b5a8262001aef565b604082019050919050565b6000602082019050818103600083015262001b808162001b3e565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203360008201527f3220626974730000000000000000000000000000000000000000000000000000602082015250565b600062001be560268362001838565b915062001bf28262001b87565b604082019050919050565b6000602082019050818103600083015262001c188162001bd6565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600062001c5760108362001838565b915062001c648262001c1f565b602082019050919050565b6000602082019050818103600083015262001c8a8162001c48565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203460008201527f3820626974730000000000000000000000000000000000000000000000000000602082015250565b600062001cef60268362001838565b915062001cfc8262001c91565b604082019050919050565b6000602082019050818103600083015262001d228162001ce0565b9050919050565b600060408201905062001d40600083018562001785565b62001d4f602083018462001785565b9392505050565b600062001d638262001303565b915062001d708362001303565b925082820390508181111562001d8b5762001d8a6200153e565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60805160a05160c05160e051610100516101205161014051615a6562001e1b6000396000610f8601526000610f5201526000612f9701526000612f760152600061217c015260006121d2015260006121fb0152615a656000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c8063715018a61161013b578063981b24d0116100b8578063d505accf1161007c578063d505accf14610733578063d9d98ce41461074f578063dd62ed3e1461077f578063f1127ed8146107af578063f2fde38b146107df57610248565b8063981b24d0146106575780639ab24eb014610687578063a457c2d7146106b7578063a9059cbb146106e7578063c3cda5201461071757610248565b80638da5cb5b116100ff5780638da5cb5b146105c35780638e539e8c146105e157806391ddadf41461061157806395d89b411461062f5780639711715a1461064d57610248565b8063715018a61461053f57806379cc6790146105495780637ecebe00146105655780638456cb591461059557806384b0196e1461059f57610248565b806342966c68116101c95780635c975abb1161018d5780635c975abb146104615780635cffe9de1461047f578063613255ab146104af5780636fcfff45146104df57806370a082311461050f57610248565b806342966c68146103ab5780634bf5d7e9146103c75780634ee2cd7e146103e5578063587cde1e146104155780635c19a95c1461044557610248565b80633644e515116102105780633644e5151461030757806339509351146103255780633a46b1a8146103555780633f4ba83a1461038557806340c10f191461038f57610248565b806306fdde031461024d578063095ea7b31461026b57806318160ddd1461029b57806323b872dd146102b9578063313ce567146102e9575b600080fd5b6102556107fb565b6040516102629190613a81565b60405180910390f35b61028560048036038101906102809190613b41565b61088d565b6040516102929190613b9c565b60405180910390f35b6102a36108b0565b6040516102b09190613bc6565b60405180910390f35b6102d360048036038101906102ce9190613be1565b6108ba565b6040516102e09190613b9c565b60405180910390f35b6102f16108e9565b6040516102fe9190613c50565b60405180910390f35b61030f6108f2565b60405161031c9190613c84565b60405180910390f35b61033f600480360381019061033a9190613b41565b610901565b60405161034c9190613b9c565b60405180910390f35b61036f600480360381019061036a9190613b41565b610938565b60405161037c9190613bc6565b60405180910390f35b61038d6109db565b005b6103a960048036038101906103a49190613b41565b6109ed565b005b6103c560048036038101906103c09190613c9f565b610a03565b005b6103cf610a17565b6040516103dc9190613a81565b60405180910390f35b6103ff60048036038101906103fa9190613b41565b610aa5565b60405161040c9190613bc6565b60405180910390f35b61042f600480360381019061042a9190613ccc565b610b15565b60405161043c9190613d08565b60405180910390f35b61045f600480360381019061045a9190613ccc565b610b7e565b005b610469610b92565b6040516104769190613b9c565b60405180910390f35b61049960048036038101906104949190613dc6565b610ba9565b6040516104a69190613b9c565b60405180910390f35b6104c960048036038101906104c49190613ccc565b610d96565b6040516104d69190613bc6565b60405180910390f35b6104f960048036038101906104f49190613ccc565b610e0d565b6040516105069190613e6d565b60405180910390f35b61052960048036038101906105249190613ccc565b610e61565b6040516105369190613bc6565b60405180910390f35b610547610ea9565b005b610563600480360381019061055e9190613b41565b610ebd565b005b61057f600480360381019061057a9190613ccc565b610edd565b60405161058c9190613bc6565b60405180910390f35b61059d610f2d565b005b6105a7610f3f565b6040516105ba9796959493929190613f81565b60405180910390f35b6105cb611041565b6040516105d89190613d08565b60405180910390f35b6105fb60048036038101906105f69190613c9f565b61106b565b6040516106089190613bc6565b60405180910390f35b6106196110d0565b6040516106269190614026565b60405180910390f35b6106376110e0565b6040516106449190613a81565b60405180910390f35b610655611172565b005b610671600480360381019061066c9190613c9f565b611185565b60405161067e9190613bc6565b60405180910390f35b6106a1600480360381019061069c9190613ccc565b6111b6565b6040516106ae9190613bc6565b60405180910390f35b6106d160048036038101906106cc9190613b41565b6112be565b6040516106de9190613b9c565b60405180910390f35b61070160048036038101906106fc9190613b41565b611335565b60405161070e9190613b9c565b60405180910390f35b610731600480360381019061072c9190614099565b611358565b005b61074d60048036038101906107489190614126565b61145c565b005b61076960048036038101906107649190613b41565b61159e565b6040516107769190613bc6565b60405180910390f35b610799600480360381019061079491906141c8565b611620565b6040516107a69190613bc6565b60405180910390f35b6107c960048036038101906107c49190614234565b6116a7565b6040516107d691906142e9565b60405180910390f35b6107f960048036038101906107f49190613ccc565b6117b7565b005b60606003805461080a90614333565b80601f016020809104026020016040519081016040528092919081815260200182805461083690614333565b80156108835780601f1061085857610100808354040283529160200191610883565b820191906000526020600020905b81548152906001019060200180831161086657829003601f168201915b5050505050905090565b600080610898611ca5565b90506108a5818585611cad565b600191505092915050565b6000600254905090565b6000806108c5611ca5565b90506108d2858285611e76565b6108dd858585611f02565b60019150509392505050565b60006012905090565b60006108fc612178565b905090565b60008061090c611ca5565b905061092d81858561091e8589611620565b6109289190614393565b611cad565b600191505092915050565b60006109426110d0565b65ffffffffffff16821061098b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098290614413565b60405180910390fd5b6109d3600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208361222f565b905092915050565b6109e3612377565b6109eb6123f5565b565b6109f5612377565b6109ff8282612458565b5050565b610a14610a0e611ca5565b82612466565b50565b606043610a226110d0565b65ffffffffffff1614610a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a619061447f565b60405180910390fd5b6040518060400160405280601d81526020017f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000815250905090565b6000806000610af284600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612474565b9150915081610b0957610b0485610e61565b610b0b565b805b9250505092915050565b6000600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610b8f610b89611ca5565b82612569565b50565b6000600960149054906101000a900460ff16905090565b6000610bb485610d96565b841115610bf6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bed90614511565b60405180910390fd5b6000610c02868661159e565b9050610c0e8786612458565b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd98773ffffffffffffffffffffffffffffffffffffffff166323e30c8b338989868a8a6040518763ffffffff1660e01b8152600401610c729695949392919061457e565b6020604051808303816000875af1158015610c91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb591906145ef565b14610cf5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cec9061468e565b60405180910390fd5b6000610cff612683565b9050610d1788308489610d129190614393565b611e76565b6000821480610d525750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b15610d7157610d6c888388610d679190614393565b612466565b610d87565b610d7b8887612466565b610d86888284611f02565b5b60019250505095945050505050565b60003073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610dd2576000610e06565b610dda6108b0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610e0591906146ae565b5b9050919050565b6000610e5a600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050611aec565b9050919050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610eb1612377565b610ebb6000612688565b565b610ecf82610ec9611ca5565b83611e76565b610ed98282612466565b5050565b6000610f26600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c97565b9050919050565b610f35612377565b610f3d61274e565b565b600060608060008060006060610f7f600a7f00000000000000000000000000000000000000000000000000000000000000006127b190919063ffffffff16565b610fb3600b7f00000000000000000000000000000000000000000000000000000000000000006127b190919063ffffffff16565b46306000801b600067ffffffffffffffff811115610fd457610fd36146e2565b5b6040519080825280602002602001820160405280156110025781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006110756110d0565b65ffffffffffff1682106110be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b590614413565b60405180910390fd5b6110c960108361222f565b9050919050565b60006110db43611c22565b905090565b6060600480546110ef90614333565b80601f016020809104026020016040519081016040528092919081815260200182805461111b90614333565b80156111685780601f1061113d57610100808354040283529160200191611168565b820191906000526020600020905b81548152906001019060200180831161114b57829003601f168201915b5050505050905090565b61117a612377565b611182612861565b50565b6000806000611195846006612474565b91509150816111ab576111a66108b0565b6111ad565b805b92505050919050565b600080600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905090506000811461129557600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600182038154811061125a57611259614711565b5b9060005260206000200160000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16611298565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16915050919050565b6000806112c9611ca5565b905060006112d78286611620565b90508381101561131c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611313906147b2565b60405180910390fd5b6113298286868403611cad565b60019250505092915050565b600080611340611ca5565b905061134d818585611f02565b600191505092915050565b8342111561139b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113929061481e565b60405180910390fd5b60006113fd6113f57fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8989896040516020016113da949392919061483e565b604051602081830303815290604052805190602001206128b7565b8585856128d1565b9050611408816128fc565b8614611449576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611440906148cf565b60405180910390fd5b6114538188612569565b50505050505050565b8342111561149f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114969061493b565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886114ce8c6128fc565b896040516020016114e49695949392919061495b565b6040516020818303038152906040528051906020012090506000611507826128b7565b90506000611517828787876128d1565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611587576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161157e90614a08565b60405180910390fd5b6115928a8a8a611cad565b50505050505050505050565b60003073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461160e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160590614a74565b60405180910390fd5b611618838361295a565b905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6116af6139b3565b600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208263ffffffff168154811061170657611705614711565b5b906000526020600020016040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050905092915050565b6117bf612377565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361182e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182590614b06565b60405180910390fd5b61183781612688565b50565b60006020835110156118565761184f83612962565b9050611878565b826118608361187e565b600001908161186f9190614cd2565b5060ff60001b90505b92915050565b6000819050919050565b6118928282611915565b61189a6129ca565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166118c06108b0565b1115611901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118f890614e16565b60405180910390fd5b61190f6010611a6b836129ee565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611984576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197b90614e82565b60405180910390fd5b61199060008383612cc9565b80600260008282546119a29190614393565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611a539190613bc6565b60405180910390a3611a6760008383612ce1565b5050565b60008183611a799190614393565b905092915050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8016821115611ae4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611adb90614f14565b60405180910390fd5b819050919050565b600063ffffffff8016821115611b37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2e90614fa6565b60405180910390fd5b819050919050565b611b4a838383611c77565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611b9457611b8782612cf1565b611b8f612d44565b611bf2565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611bde57611bd183612cf1565b611bd9612d44565b611bf1565b611be783612cf1565b611bf082612cf1565b5b5b505050565b611c02838383611c7c565b611c1d611c0e84610b15565b611c1784610b15565b83612d58565b505050565b600065ffffffffffff8016821115611c6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6690615038565b60405180910390fd5b819050919050565b505050565b505050565b60008183611c8f91906146ae565b905092915050565b600081600001549050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611d1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d13906150ca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d829061515c565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051611e699190613bc6565b60405180910390a3505050565b6000611e828484611620565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611efc5781811015611eee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ee5906151c8565b60405180910390fd5b611efb8484848403611cad565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611f71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f689061525a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611fe0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd7906152ec565b60405180910390fd5b611feb838383612cc9565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612071576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120689061537e565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161215f9190613bc6565b60405180910390a3612172848484612ce1565b50505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480156121f457507f000000000000000000000000000000000000000000000000000000000000000046145b15612221577f0000000000000000000000000000000000000000000000000000000000000000905061222c565b612229612f51565b90505b90565b6000808380549050905060008082905060058311156122a557600061225384612fe7565b8461225e91906146ae565b90508561226b88836130e0565b60000160009054906101000a900463ffffffff1663ffffffff161115612293578091506122a3565b6001816122a09190614393565b92505b505b5b808210156123055760006122ba83836130f5565b9050856122c788836130e0565b60000160009054906101000a900463ffffffff1663ffffffff1611156122ef578091506122ff565b6001816122fc9190614393565b92505b506122a6565b6000811461234b5761231a86600183036130e0565b60000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661234e565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16935050505092915050565b61237f611ca5565b73ffffffffffffffffffffffffffffffffffffffff1661239d611041565b73ffffffffffffffffffffffffffffffffffffffff16146123f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ea906153ea565b60405180910390fd5b565b6123fd61311b565b6000600960146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612441611ca5565b60405161244e9190613d08565b60405180910390a1565b6124628282611888565b5050565b6124708282613164565b5050565b600080600084116124ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124b190615456565b60405180910390fd5b6124c2613182565b841115612504576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124fb906154c2565b60405180910390fd5b600061251c858560000161319390919063ffffffff16565b905083600001805490508103612539576000809250925050612562565b600184600101828154811061255157612550614711565b5b906000526020600020015492509250505b9250929050565b600061257483610b15565b9050600061258184610e61565b905082600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a461267d828483612d58565b50505050565b600090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61275661324c565b6001600960146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861279a611ca5565b6040516127a79190613d08565b60405180910390a1565b606060ff60001b83146127ce576127c783613296565b905061285b565b8180546127da90614333565b80601f016020809104026020016040519081016040528092919081815260200182805461280690614333565b80156128535780601f1061282857610100808354040283529160200191612853565b820191906000526020600020905b81548152906001019060200180831161283657829003601f168201915b505050505090505b92915050565b600061286d600861330a565b6000612877613182565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67816040516128a89190613bc6565b60405180910390a18091505090565b60006128ca6128c4612178565b83613320565b9050919050565b60008060006128e287878787613361565b915091506128ef81613443565b8192505050949350505050565b600080600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905061294981611c97565b91506129548161330a565b50919050565b600092915050565b600080829050601f815111156129af57826040517f305a27a90000000000000000000000000000000000000000000000000000000081526004016129a69190613a81565b60405180910390fd5b8051816129bb90615512565b60001c1760001b915050919050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b6000806000858054905090506000808214612ab457612a1087600184036130e0565b6040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050612af0565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152505b905080602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169350612b2584868863ffffffff16565b9250600082118015612b4f5750612b3a6110d0565b65ffffffffffff16816000015163ffffffff16145b15612bc057612b5d83611a81565b612b6a88600185036130e0565b60000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550612cbf565b866040518060400160405280612be4612bd76110d0565b65ffffffffffff16611aec565b63ffffffff168152602001612bf886611a81565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555050505b5050935093915050565b612cd161324c565b612cdc838383611b3f565b505050565b612cec838383611bf7565b505050565b612d41600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d3c83610e61565b6135a9565b50565b612d566006612d516108b0565b6135a9565b565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612d945750600081115b15612f4c57600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612e7257600080612e1b600f60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c81856129ee565b915091508473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051612e67929190615579565b60405180910390a250505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612f4b57600080612ef4600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611a6b856129ee565b915091508373ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051612f40929190615579565b60405180910390a250505b5b505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000004630604051602001612fcc9594939291906155a2565b60405160208183030381529060405280519060200120905090565b6000808203612ff957600090506130db565b6000600161300684613624565b901c6001901b905060018184816130205761301f6155f5565b5b048201901c90506001818481613039576130386155f5565b5b048201901c90506001818481613052576130516155f5565b5b048201901c9050600181848161306b5761306a6155f5565b5b048201901c90506001818481613084576130836155f5565b5b048201901c9050600181848161309d5761309c6155f5565b5b048201901c905060018184816130b6576130b56155f5565b5b048201901c90506130d7818285816130d1576130d06155f5565b5b04613705565b9150505b919050565b60008260005281602060002001905092915050565b600060028284186131069190615624565b8284166131139190614393565b905092915050565b613123610b92565b613162576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613159906156a1565b60405180910390fd5b565b61316e828261371e565b61317c6010611c81836129ee565b50505050565b600061318e6008611c97565b905090565b6000808380549050036131a95760009050613246565b600080848054905090505b808210156131fd5760006131c883836130f5565b9050846131d587836138eb565b6000015411156131e7578091506131f7565b6001816131f49190614393565b92505b506131b4565b60008211801561322557508361321f8660018561321a91906146ae565b6138eb565b60000154145b156132405760018261323791906146ae565b92505050613246565b81925050505b92915050565b613254610b92565b15613294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161328b9061570d565b60405180910390fd5b565b606060006132a38361390d565b90506000602067ffffffffffffffff8111156132c2576132c16146e2565b5b6040519080825280601f01601f1916602001820160405280156132f45781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b6001816000016000828254019250508190555050565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c111561339c57600060039150915061343a565b6000600187878787604051600081526020016040526040516133c1949392919061572d565b6020604051602081039080840390855afa1580156133e3573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036134315760006001925092505061343a565b80600092509250505b94509492505050565b6000600481111561345757613456615772565b5b81600481111561346a57613469615772565b5b03156135a6576001600481111561348457613483615772565b5b81600481111561349757613496615772565b5b036134d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134ce906157ed565b60405180910390fd5b600260048111156134eb576134ea615772565b5b8160048111156134fe576134fd615772565b5b0361353e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161353590615859565b60405180910390fd5b6003600481111561355257613551615772565b5b81600481111561356557613564615772565b5b036135a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161359c906158eb565b60405180910390fd5b5b50565b60006135b3613182565b9050806135c28460000161395d565b101561361f5782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b600080600090506000608084901c111561364657608083901c92506080810190505b6000604084901c111561366157604083901c92506040810190505b6000602084901c111561367c57602083901c92506020810190505b6000601084901c111561369757601083901c92506010810190505b6000600884901c11156136b257600883901c92506008810190505b6000600484901c11156136cd57600483901c92506004810190505b6000600284901c11156136e857600283901c92506002810190505b6000600184901c11156136fc576001810190505b80915050919050565b60008183106137145781613716565b825b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361378d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137849061597d565b60405180910390fd5b61379982600083612cc9565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561381f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161381690615a0f565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008282540392505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516138d29190613bc6565b60405180910390a36138e683600084612ce1565b505050565b60008083600052826020600020019050613904816139a9565b91505092915050565b60008060ff8360001c169050601f811115613954576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b60008082805490500361397357600090506139a4565b816001838054905061398591906146ae565b8154811061399657613995614711565b5b906000526020600020015490505b919050565b6000819050919050565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090565b600081519050919050565b600082825260208201905092915050565b60005b83811015613a2b578082015181840152602081019050613a10565b60008484015250505050565b6000601f19601f8301169050919050565b6000613a53826139f1565b613a5d81856139fc565b9350613a6d818560208601613a0d565b613a7681613a37565b840191505092915050565b60006020820190508181036000830152613a9b8184613a48565b905092915050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613ad882613aad565b9050919050565b613ae881613acd565b8114613af357600080fd5b50565b600081359050613b0581613adf565b92915050565b6000819050919050565b613b1e81613b0b565b8114613b2957600080fd5b50565b600081359050613b3b81613b15565b92915050565b60008060408385031215613b5857613b57613aa3565b5b6000613b6685828601613af6565b9250506020613b7785828601613b2c565b9150509250929050565b60008115159050919050565b613b9681613b81565b82525050565b6000602082019050613bb16000830184613b8d565b92915050565b613bc081613b0b565b82525050565b6000602082019050613bdb6000830184613bb7565b92915050565b600080600060608486031215613bfa57613bf9613aa3565b5b6000613c0886828701613af6565b9350506020613c1986828701613af6565b9250506040613c2a86828701613b2c565b9150509250925092565b600060ff82169050919050565b613c4a81613c34565b82525050565b6000602082019050613c656000830184613c41565b92915050565b6000819050919050565b613c7e81613c6b565b82525050565b6000602082019050613c996000830184613c75565b92915050565b600060208284031215613cb557613cb4613aa3565b5b6000613cc384828501613b2c565b91505092915050565b600060208284031215613ce257613ce1613aa3565b5b6000613cf084828501613af6565b91505092915050565b613d0281613acd565b82525050565b6000602082019050613d1d6000830184613cf9565b92915050565b6000613d2e82613acd565b9050919050565b613d3e81613d23565b8114613d4957600080fd5b50565b600081359050613d5b81613d35565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112613d8657613d85613d61565b5b8235905067ffffffffffffffff811115613da357613da2613d66565b5b602083019150836001820283011115613dbf57613dbe613d6b565b5b9250929050565b600080600080600060808688031215613de257613de1613aa3565b5b6000613df088828901613d4c565b9550506020613e0188828901613af6565b9450506040613e1288828901613b2c565b935050606086013567ffffffffffffffff811115613e3357613e32613aa8565b5b613e3f88828901613d70565b92509250509295509295909350565b600063ffffffff82169050919050565b613e6781613e4e565b82525050565b6000602082019050613e826000830184613e5e565b92915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b613ebd81613e88565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613ef881613b0b565b82525050565b6000613f0a8383613eef565b60208301905092915050565b6000602082019050919050565b6000613f2e82613ec3565b613f388185613ece565b9350613f4383613edf565b8060005b83811015613f74578151613f5b8882613efe565b9750613f6683613f16565b925050600181019050613f47565b5085935050505092915050565b600060e082019050613f96600083018a613eb4565b8181036020830152613fa88189613a48565b90508181036040830152613fbc8188613a48565b9050613fcb6060830187613bb7565b613fd86080830186613cf9565b613fe560a0830185613c75565b81810360c0830152613ff78184613f23565b905098975050505050505050565b600065ffffffffffff82169050919050565b61402081614005565b82525050565b600060208201905061403b6000830184614017565b92915050565b61404a81613c34565b811461405557600080fd5b50565b60008135905061406781614041565b92915050565b61407681613c6b565b811461408157600080fd5b50565b6000813590506140938161406d565b92915050565b60008060008060008060c087890312156140b6576140b5613aa3565b5b60006140c489828a01613af6565b96505060206140d589828a01613b2c565b95505060406140e689828a01613b2c565b94505060606140f789828a01614058565b935050608061410889828a01614084565b92505060a061411989828a01614084565b9150509295509295509295565b600080600080600080600060e0888a03121561414557614144613aa3565b5b60006141538a828b01613af6565b97505060206141648a828b01613af6565b96505060406141758a828b01613b2c565b95505060606141868a828b01613b2c565b94505060806141978a828b01614058565b93505060a06141a88a828b01614084565b92505060c06141b98a828b01614084565b91505092959891949750929550565b600080604083850312156141df576141de613aa3565b5b60006141ed85828601613af6565b92505060206141fe85828601613af6565b9150509250929050565b61421181613e4e565b811461421c57600080fd5b50565b60008135905061422e81614208565b92915050565b6000806040838503121561424b5761424a613aa3565b5b600061425985828601613af6565b925050602061426a8582860161421f565b9150509250929050565b61427d81613e4e565b82525050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6142b481614283565b82525050565b6040820160008201516142d06000850182614274565b5060208201516142e360208501826142ab565b50505050565b60006040820190506142fe60008301846142ba565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061434b57607f821691505b60208210810361435e5761435d614304565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061439e82613b0b565b91506143a983613b0b565b92508282019050808211156143c1576143c0614364565b5b92915050565b7f4552433230566f7465733a20667574757265206c6f6f6b757000000000000000600082015250565b60006143fd6019836139fc565b9150614408826143c7565b602082019050919050565b6000602082019050818103600083015261442c816143f0565b9050919050565b7f4552433230566f7465733a2062726f6b656e20636c6f636b206d6f6465000000600082015250565b6000614469601d836139fc565b915061447482614433565b602082019050919050565b600060208201905081810360008301526144988161445c565b9050919050565b7f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60008201527f6178466c6173684c6f616e000000000000000000000000000000000000000000602082015250565b60006144fb602b836139fc565b91506145068261449f565b604082019050919050565b6000602082019050818103600083015261452a816144ee565b9050919050565b600082825260208201905092915050565b82818337600083830152505050565b600061455d8385614531565b935061456a838584614542565b61457383613a37565b840190509392505050565b600060a0820190506145936000830189613cf9565b6145a06020830188613cf9565b6145ad6040830187613bb7565b6145ba6060830186613bb7565b81810360808301526145cd818486614551565b9050979650505050505050565b6000815190506145e98161406d565b92915050565b60006020828403121561460557614604613aa3565b5b6000614613848285016145da565b91505092915050565b7f4552433230466c6173684d696e743a20696e76616c69642072657475726e207660008201527f616c756500000000000000000000000000000000000000000000000000000000602082015250565b60006146786024836139fc565b91506146838261461c565b604082019050919050565b600060208201905081810360008301526146a78161466b565b9050919050565b60006146b982613b0b565b91506146c483613b0b565b92508282039050818111156146dc576146db614364565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b600061479c6025836139fc565b91506147a782614740565b604082019050919050565b600060208201905081810360008301526147cb8161478f565b9050919050565b7f4552433230566f7465733a207369676e61747572652065787069726564000000600082015250565b6000614808601d836139fc565b9150614813826147d2565b602082019050919050565b60006020820190508181036000830152614837816147fb565b9050919050565b60006080820190506148536000830187613c75565b6148606020830186613cf9565b61486d6040830185613bb7565b61487a6060830184613bb7565b95945050505050565b7f4552433230566f7465733a20696e76616c6964206e6f6e636500000000000000600082015250565b60006148b96019836139fc565b91506148c482614883565b602082019050919050565b600060208201905081810360008301526148e8816148ac565b9050919050565b7f45524332305065726d69743a206578706972656420646561646c696e65000000600082015250565b6000614925601d836139fc565b9150614930826148ef565b602082019050919050565b6000602082019050818103600083015261495481614918565b9050919050565b600060c0820190506149706000830189613c75565b61497d6020830188613cf9565b61498a6040830187613cf9565b6149976060830186613bb7565b6149a46080830185613bb7565b6149b160a0830184613bb7565b979650505050505050565b7f45524332305065726d69743a20696e76616c6964207369676e61747572650000600082015250565b60006149f2601e836139fc565b91506149fd826149bc565b602082019050919050565b60006020820190508181036000830152614a21816149e5565b9050919050565b7f4552433230466c6173684d696e743a2077726f6e6720746f6b656e0000000000600082015250565b6000614a5e601b836139fc565b9150614a6982614a28565b602082019050919050565b60006020820190508181036000830152614a8d81614a51565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614af06026836139fc565b9150614afb82614a94565b604082019050919050565b60006020820190508181036000830152614b1f81614ae3565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614b887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614b4b565b614b928683614b4b565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614bcf614bca614bc584613b0b565b614baa565b613b0b565b9050919050565b6000819050919050565b614be983614bb4565b614bfd614bf582614bd6565b848454614b58565b825550505050565b600090565b614c12614c05565b614c1d818484614be0565b505050565b5b81811015614c4157614c36600082614c0a565b600181019050614c23565b5050565b601f821115614c8657614c5781614b26565b614c6084614b3b565b81016020851015614c6f578190505b614c83614c7b85614b3b565b830182614c22565b50505b505050565b600082821c905092915050565b6000614ca960001984600802614c8b565b1980831691505092915050565b6000614cc28383614c98565b9150826002028217905092915050565b614cdb826139f1565b67ffffffffffffffff811115614cf457614cf36146e2565b5b614cfe8254614333565b614d09828285614c45565b600060209050601f831160018114614d3c5760008415614d2a578287015190505b614d348582614cb6565b865550614d9c565b601f198416614d4a86614b26565b60005b82811015614d7257848901518255600182019150602085019450602081019050614d4d565b86831015614d8f5784890151614d8b601f891682614c98565b8355505b6001600288020188555050505b505050505050565b7f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60008201527f766572666c6f77696e6720766f74657300000000000000000000000000000000602082015250565b6000614e006030836139fc565b9150614e0b82614da4565b604082019050919050565b60006020820190508181036000830152614e2f81614df3565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b6000614e6c601f836139fc565b9150614e7782614e36565b602082019050919050565b60006020820190508181036000830152614e9b81614e5f565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203260008201527f3234206269747300000000000000000000000000000000000000000000000000602082015250565b6000614efe6027836139fc565b9150614f0982614ea2565b604082019050919050565b60006020820190508181036000830152614f2d81614ef1565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203360008201527f3220626974730000000000000000000000000000000000000000000000000000602082015250565b6000614f906026836139fc565b9150614f9b82614f34565b604082019050919050565b60006020820190508181036000830152614fbf81614f83565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203460008201527f3820626974730000000000000000000000000000000000000000000000000000602082015250565b60006150226026836139fc565b915061502d82614fc6565b604082019050919050565b6000602082019050818103600083015261505181615015565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006150b46024836139fc565b91506150bf82615058565b604082019050919050565b600060208201905081810360008301526150e3816150a7565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b60006151466022836139fc565b9150615151826150ea565b604082019050919050565b6000602082019050818103600083015261517581615139565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b60006151b2601d836139fc565b91506151bd8261517c565b602082019050919050565b600060208201905081810360008301526151e1816151a5565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006152446025836139fc565b915061524f826151e8565b604082019050919050565b6000602082019050818103600083015261527381615237565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b60006152d66023836139fc565b91506152e18261527a565b604082019050919050565b60006020820190508181036000830152615305816152c9565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b60006153686026836139fc565b91506153738261530c565b604082019050919050565b600060208201905081810360008301526153978161535b565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006153d46020836139fc565b91506153df8261539e565b602082019050919050565b60006020820190508181036000830152615403816153c7565b9050919050565b7f4552433230536e617073686f743a206964206973203000000000000000000000600082015250565b60006154406016836139fc565b915061544b8261540a565b602082019050919050565b6000602082019050818103600083015261546f81615433565b9050919050565b7f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000600082015250565b60006154ac601d836139fc565b91506154b782615476565b602082019050919050565b600060208201905081810360008301526154db8161549f565b9050919050565b600081519050919050565b6000819050602082019050919050565b60006155098251613c6b565b80915050919050565b600061551d826154e2565b82615527846154ed565b9050615532816154fd565b925060208210156155725761556d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802614b4b565b831692505b5050919050565b600060408201905061558e6000830185613bb7565b61559b6020830184613bb7565b9392505050565b600060a0820190506155b76000830188613c75565b6155c46020830187613c75565b6155d16040830186613c75565b6155de6060830185613bb7565b6155eb6080830184613cf9565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061562f82613b0b565b915061563a83613b0b565b92508261564a576156496155f5565b5b828204905092915050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b600061568b6014836139fc565b915061569682615655565b602082019050919050565b600060208201905081810360008301526156ba8161567e565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b60006156f76010836139fc565b9150615702826156c1565b602082019050919050565b60006020820190508181036000830152615726816156ea565b9050919050565b60006080820190506157426000830187613c75565b61574f6020830186613c41565b61575c6040830185613c75565b6157696060830184613c75565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b60006157d76018836139fc565b91506157e2826157a1565b602082019050919050565b60006020820190508181036000830152615806816157ca565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615843601f836139fc565b915061584e8261580d565b602082019050919050565b6000602082019050818103600083015261587281615836565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b60006158d56022836139fc565b91506158e082615879565b604082019050919050565b60006020820190508181036000830152615904816158c8565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b60006159676021836139fc565b91506159728261590b565b604082019050919050565b600060208201905081810360008301526159968161595a565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b60006159f96022836139fc565b9150615a048261599d565b604082019050919050565b60006020820190508181036000830152615a28816159ec565b905091905056fea26469706673582212201e3a95ac0ea6e47958a92f595fe6c769b6cfaf49b623370daaaf649523da853e64736f6c63430008120033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102485760003560e01c8063715018a61161013b578063981b24d0116100b8578063d505accf1161007c578063d505accf14610733578063d9d98ce41461074f578063dd62ed3e1461077f578063f1127ed8146107af578063f2fde38b146107df57610248565b8063981b24d0146106575780639ab24eb014610687578063a457c2d7146106b7578063a9059cbb146106e7578063c3cda5201461071757610248565b80638da5cb5b116100ff5780638da5cb5b146105c35780638e539e8c146105e157806391ddadf41461061157806395d89b411461062f5780639711715a1461064d57610248565b8063715018a61461053f57806379cc6790146105495780637ecebe00146105655780638456cb591461059557806384b0196e1461059f57610248565b806342966c68116101c95780635c975abb1161018d5780635c975abb146104615780635cffe9de1461047f578063613255ab146104af5780636fcfff45146104df57806370a082311461050f57610248565b806342966c68146103ab5780634bf5d7e9146103c75780634ee2cd7e146103e5578063587cde1e146104155780635c19a95c1461044557610248565b80633644e515116102105780633644e5151461030757806339509351146103255780633a46b1a8146103555780633f4ba83a1461038557806340c10f191461038f57610248565b806306fdde031461024d578063095ea7b31461026b57806318160ddd1461029b57806323b872dd146102b9578063313ce567146102e9575b600080fd5b6102556107fb565b6040516102629190613a81565b60405180910390f35b61028560048036038101906102809190613b41565b61088d565b6040516102929190613b9c565b60405180910390f35b6102a36108b0565b6040516102b09190613bc6565b60405180910390f35b6102d360048036038101906102ce9190613be1565b6108ba565b6040516102e09190613b9c565b60405180910390f35b6102f16108e9565b6040516102fe9190613c50565b60405180910390f35b61030f6108f2565b60405161031c9190613c84565b60405180910390f35b61033f600480360381019061033a9190613b41565b610901565b60405161034c9190613b9c565b60405180910390f35b61036f600480360381019061036a9190613b41565b610938565b60405161037c9190613bc6565b60405180910390f35b61038d6109db565b005b6103a960048036038101906103a49190613b41565b6109ed565b005b6103c560048036038101906103c09190613c9f565b610a03565b005b6103cf610a17565b6040516103dc9190613a81565b60405180910390f35b6103ff60048036038101906103fa9190613b41565b610aa5565b60405161040c9190613bc6565b60405180910390f35b61042f600480360381019061042a9190613ccc565b610b15565b60405161043c9190613d08565b60405180910390f35b61045f600480360381019061045a9190613ccc565b610b7e565b005b610469610b92565b6040516104769190613b9c565b60405180910390f35b61049960048036038101906104949190613dc6565b610ba9565b6040516104a69190613b9c565b60405180910390f35b6104c960048036038101906104c49190613ccc565b610d96565b6040516104d69190613bc6565b60405180910390f35b6104f960048036038101906104f49190613ccc565b610e0d565b6040516105069190613e6d565b60405180910390f35b61052960048036038101906105249190613ccc565b610e61565b6040516105369190613bc6565b60405180910390f35b610547610ea9565b005b610563600480360381019061055e9190613b41565b610ebd565b005b61057f600480360381019061057a9190613ccc565b610edd565b60405161058c9190613bc6565b60405180910390f35b61059d610f2d565b005b6105a7610f3f565b6040516105ba9796959493929190613f81565b60405180910390f35b6105cb611041565b6040516105d89190613d08565b60405180910390f35b6105fb60048036038101906105f69190613c9f565b61106b565b6040516106089190613bc6565b60405180910390f35b6106196110d0565b6040516106269190614026565b60405180910390f35b6106376110e0565b6040516106449190613a81565b60405180910390f35b610655611172565b005b610671600480360381019061066c9190613c9f565b611185565b60405161067e9190613bc6565b60405180910390f35b6106a1600480360381019061069c9190613ccc565b6111b6565b6040516106ae9190613bc6565b60405180910390f35b6106d160048036038101906106cc9190613b41565b6112be565b6040516106de9190613b9c565b60405180910390f35b61070160048036038101906106fc9190613b41565b611335565b60405161070e9190613b9c565b60405180910390f35b610731600480360381019061072c9190614099565b611358565b005b61074d60048036038101906107489190614126565b61145c565b005b61076960048036038101906107649190613b41565b61159e565b6040516107769190613bc6565b60405180910390f35b610799600480360381019061079491906141c8565b611620565b6040516107a69190613bc6565b60405180910390f35b6107c960048036038101906107c49190614234565b6116a7565b6040516107d691906142e9565b60405180910390f35b6107f960048036038101906107f49190613ccc565b6117b7565b005b60606003805461080a90614333565b80601f016020809104026020016040519081016040528092919081815260200182805461083690614333565b80156108835780601f1061085857610100808354040283529160200191610883565b820191906000526020600020905b81548152906001019060200180831161086657829003601f168201915b5050505050905090565b600080610898611ca5565b90506108a5818585611cad565b600191505092915050565b6000600254905090565b6000806108c5611ca5565b90506108d2858285611e76565b6108dd858585611f02565b60019150509392505050565b60006012905090565b60006108fc612178565b905090565b60008061090c611ca5565b905061092d81858561091e8589611620565b6109289190614393565b611cad565b600191505092915050565b60006109426110d0565b65ffffffffffff16821061098b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098290614413565b60405180910390fd5b6109d3600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208361222f565b905092915050565b6109e3612377565b6109eb6123f5565b565b6109f5612377565b6109ff8282612458565b5050565b610a14610a0e611ca5565b82612466565b50565b606043610a226110d0565b65ffffffffffff1614610a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a619061447f565b60405180910390fd5b6040518060400160405280601d81526020017f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000815250905090565b6000806000610af284600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612474565b9150915081610b0957610b0485610e61565b610b0b565b805b9250505092915050565b6000600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610b8f610b89611ca5565b82612569565b50565b6000600960149054906101000a900460ff16905090565b6000610bb485610d96565b841115610bf6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bed90614511565b60405180910390fd5b6000610c02868661159e565b9050610c0e8786612458565b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd98773ffffffffffffffffffffffffffffffffffffffff166323e30c8b338989868a8a6040518763ffffffff1660e01b8152600401610c729695949392919061457e565b6020604051808303816000875af1158015610c91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb591906145ef565b14610cf5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cec9061468e565b60405180910390fd5b6000610cff612683565b9050610d1788308489610d129190614393565b611e76565b6000821480610d525750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b15610d7157610d6c888388610d679190614393565b612466565b610d87565b610d7b8887612466565b610d86888284611f02565b5b60019250505095945050505050565b60003073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610dd2576000610e06565b610dda6108b0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610e0591906146ae565b5b9050919050565b6000610e5a600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050611aec565b9050919050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610eb1612377565b610ebb6000612688565b565b610ecf82610ec9611ca5565b83611e76565b610ed98282612466565b5050565b6000610f26600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c97565b9050919050565b610f35612377565b610f3d61274e565b565b600060608060008060006060610f7f600a7f5265616c205374726177626572727920456c657068616e7400000000000000186127b190919063ffffffff16565b610fb3600b7f31000000000000000000000000000000000000000000000000000000000000016127b190919063ffffffff16565b46306000801b600067ffffffffffffffff811115610fd457610fd36146e2565b5b6040519080825280602002602001820160405280156110025781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006110756110d0565b65ffffffffffff1682106110be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b590614413565b60405180910390fd5b6110c960108361222f565b9050919050565b60006110db43611c22565b905090565b6060600480546110ef90614333565b80601f016020809104026020016040519081016040528092919081815260200182805461111b90614333565b80156111685780601f1061113d57610100808354040283529160200191611168565b820191906000526020600020905b81548152906001019060200180831161114b57829003601f168201915b5050505050905090565b61117a612377565b611182612861565b50565b6000806000611195846006612474565b91509150816111ab576111a66108b0565b6111ad565b805b92505050919050565b600080600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905090506000811461129557600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600182038154811061125a57611259614711565b5b9060005260206000200160000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16611298565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16915050919050565b6000806112c9611ca5565b905060006112d78286611620565b90508381101561131c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611313906147b2565b60405180910390fd5b6113298286868403611cad565b60019250505092915050565b600080611340611ca5565b905061134d818585611f02565b600191505092915050565b8342111561139b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113929061481e565b60405180910390fd5b60006113fd6113f57fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8989896040516020016113da949392919061483e565b604051602081830303815290604052805190602001206128b7565b8585856128d1565b9050611408816128fc565b8614611449576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611440906148cf565b60405180910390fd5b6114538188612569565b50505050505050565b8342111561149f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114969061493b565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886114ce8c6128fc565b896040516020016114e49695949392919061495b565b6040516020818303038152906040528051906020012090506000611507826128b7565b90506000611517828787876128d1565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611587576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161157e90614a08565b60405180910390fd5b6115928a8a8a611cad565b50505050505050505050565b60003073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461160e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160590614a74565b60405180910390fd5b611618838361295a565b905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6116af6139b3565b600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208263ffffffff168154811061170657611705614711565b5b906000526020600020016040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050905092915050565b6117bf612377565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361182e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182590614b06565b60405180910390fd5b61183781612688565b50565b60006020835110156118565761184f83612962565b9050611878565b826118608361187e565b600001908161186f9190614cd2565b5060ff60001b90505b92915050565b6000819050919050565b6118928282611915565b61189a6129ca565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166118c06108b0565b1115611901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118f890614e16565b60405180910390fd5b61190f6010611a6b836129ee565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611984576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197b90614e82565b60405180910390fd5b61199060008383612cc9565b80600260008282546119a29190614393565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611a539190613bc6565b60405180910390a3611a6760008383612ce1565b5050565b60008183611a799190614393565b905092915050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8016821115611ae4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611adb90614f14565b60405180910390fd5b819050919050565b600063ffffffff8016821115611b37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2e90614fa6565b60405180910390fd5b819050919050565b611b4a838383611c77565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611b9457611b8782612cf1565b611b8f612d44565b611bf2565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611bde57611bd183612cf1565b611bd9612d44565b611bf1565b611be783612cf1565b611bf082612cf1565b5b5b505050565b611c02838383611c7c565b611c1d611c0e84610b15565b611c1784610b15565b83612d58565b505050565b600065ffffffffffff8016821115611c6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6690615038565b60405180910390fd5b819050919050565b505050565b505050565b60008183611c8f91906146ae565b905092915050565b600081600001549050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611d1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d13906150ca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d829061515c565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051611e699190613bc6565b60405180910390a3505050565b6000611e828484611620565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611efc5781811015611eee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ee5906151c8565b60405180910390fd5b611efb8484848403611cad565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611f71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f689061525a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611fe0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd7906152ec565b60405180910390fd5b611feb838383612cc9565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612071576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120689061537e565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161215f9190613bc6565b60405180910390a3612172848484612ce1565b50505050565b60007f00000000000000000000000009ad81ad47137d30a5aac0b89e3341eeaa0d6bda73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480156121f457507f000000000000000000000000000000000000000000000000000000000000000146145b15612221577feab0eb0ec6c2239ba2670f23ad96b5265c3ef1a7bb5f95a36f9b2005a4c2f226905061222c565b612229612f51565b90505b90565b6000808380549050905060008082905060058311156122a557600061225384612fe7565b8461225e91906146ae565b90508561226b88836130e0565b60000160009054906101000a900463ffffffff1663ffffffff161115612293578091506122a3565b6001816122a09190614393565b92505b505b5b808210156123055760006122ba83836130f5565b9050856122c788836130e0565b60000160009054906101000a900463ffffffff1663ffffffff1611156122ef578091506122ff565b6001816122fc9190614393565b92505b506122a6565b6000811461234b5761231a86600183036130e0565b60000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661234e565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16935050505092915050565b61237f611ca5565b73ffffffffffffffffffffffffffffffffffffffff1661239d611041565b73ffffffffffffffffffffffffffffffffffffffff16146123f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ea906153ea565b60405180910390fd5b565b6123fd61311b565b6000600960146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612441611ca5565b60405161244e9190613d08565b60405180910390a1565b6124628282611888565b5050565b6124708282613164565b5050565b600080600084116124ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124b190615456565b60405180910390fd5b6124c2613182565b841115612504576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124fb906154c2565b60405180910390fd5b600061251c858560000161319390919063ffffffff16565b905083600001805490508103612539576000809250925050612562565b600184600101828154811061255157612550614711565b5b906000526020600020015492509250505b9250929050565b600061257483610b15565b9050600061258184610e61565b905082600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a461267d828483612d58565b50505050565b600090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61275661324c565b6001600960146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861279a611ca5565b6040516127a79190613d08565b60405180910390a1565b606060ff60001b83146127ce576127c783613296565b905061285b565b8180546127da90614333565b80601f016020809104026020016040519081016040528092919081815260200182805461280690614333565b80156128535780601f1061282857610100808354040283529160200191612853565b820191906000526020600020905b81548152906001019060200180831161283657829003601f168201915b505050505090505b92915050565b600061286d600861330a565b6000612877613182565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67816040516128a89190613bc6565b60405180910390a18091505090565b60006128ca6128c4612178565b83613320565b9050919050565b60008060006128e287878787613361565b915091506128ef81613443565b8192505050949350505050565b600080600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905061294981611c97565b91506129548161330a565b50919050565b600092915050565b600080829050601f815111156129af57826040517f305a27a90000000000000000000000000000000000000000000000000000000081526004016129a69190613a81565b60405180910390fd5b8051816129bb90615512565b60001c1760001b915050919050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b6000806000858054905090506000808214612ab457612a1087600184036130e0565b6040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050612af0565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152505b905080602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169350612b2584868863ffffffff16565b9250600082118015612b4f5750612b3a6110d0565b65ffffffffffff16816000015163ffffffff16145b15612bc057612b5d83611a81565b612b6a88600185036130e0565b60000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550612cbf565b866040518060400160405280612be4612bd76110d0565b65ffffffffffff16611aec565b63ffffffff168152602001612bf886611a81565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555050505b5050935093915050565b612cd161324c565b612cdc838383611b3f565b505050565b612cec838383611bf7565b505050565b612d41600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d3c83610e61565b6135a9565b50565b612d566006612d516108b0565b6135a9565b565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612d945750600081115b15612f4c57600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612e7257600080612e1b600f60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c81856129ee565b915091508473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051612e67929190615579565b60405180910390a250505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612f4b57600080612ef4600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611a6b856129ee565b915091508373ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051612f40929190615579565b60405180910390a250505b5b505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f2d73457443008cb41eddee1c900158c034a601837c81480dcf5fe58bbc1f6ced7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001612fcc9594939291906155a2565b60405160208183030381529060405280519060200120905090565b6000808203612ff957600090506130db565b6000600161300684613624565b901c6001901b905060018184816130205761301f6155f5565b5b048201901c90506001818481613039576130386155f5565b5b048201901c90506001818481613052576130516155f5565b5b048201901c9050600181848161306b5761306a6155f5565b5b048201901c90506001818481613084576130836155f5565b5b048201901c9050600181848161309d5761309c6155f5565b5b048201901c905060018184816130b6576130b56155f5565b5b048201901c90506130d7818285816130d1576130d06155f5565b5b04613705565b9150505b919050565b60008260005281602060002001905092915050565b600060028284186131069190615624565b8284166131139190614393565b905092915050565b613123610b92565b613162576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613159906156a1565b60405180910390fd5b565b61316e828261371e565b61317c6010611c81836129ee565b50505050565b600061318e6008611c97565b905090565b6000808380549050036131a95760009050613246565b600080848054905090505b808210156131fd5760006131c883836130f5565b9050846131d587836138eb565b6000015411156131e7578091506131f7565b6001816131f49190614393565b92505b506131b4565b60008211801561322557508361321f8660018561321a91906146ae565b6138eb565b60000154145b156132405760018261323791906146ae565b92505050613246565b81925050505b92915050565b613254610b92565b15613294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161328b9061570d565b60405180910390fd5b565b606060006132a38361390d565b90506000602067ffffffffffffffff8111156132c2576132c16146e2565b5b6040519080825280601f01601f1916602001820160405280156132f45781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b6001816000016000828254019250508190555050565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c111561339c57600060039150915061343a565b6000600187878787604051600081526020016040526040516133c1949392919061572d565b6020604051602081039080840390855afa1580156133e3573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036134315760006001925092505061343a565b80600092509250505b94509492505050565b6000600481111561345757613456615772565b5b81600481111561346a57613469615772565b5b03156135a6576001600481111561348457613483615772565b5b81600481111561349757613496615772565b5b036134d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134ce906157ed565b60405180910390fd5b600260048111156134eb576134ea615772565b5b8160048111156134fe576134fd615772565b5b0361353e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161353590615859565b60405180910390fd5b6003600481111561355257613551615772565b5b81600481111561356557613564615772565b5b036135a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161359c906158eb565b60405180910390fd5b5b50565b60006135b3613182565b9050806135c28460000161395d565b101561361f5782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b600080600090506000608084901c111561364657608083901c92506080810190505b6000604084901c111561366157604083901c92506040810190505b6000602084901c111561367c57602083901c92506020810190505b6000601084901c111561369757601083901c92506010810190505b6000600884901c11156136b257600883901c92506008810190505b6000600484901c11156136cd57600483901c92506004810190505b6000600284901c11156136e857600283901c92506002810190505b6000600184901c11156136fc576001810190505b80915050919050565b60008183106137145781613716565b825b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361378d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137849061597d565b60405180910390fd5b61379982600083612cc9565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561381f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161381690615a0f565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008282540392505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516138d29190613bc6565b60405180910390a36138e683600084612ce1565b505050565b60008083600052826020600020019050613904816139a9565b91505092915050565b60008060ff8360001c169050601f811115613954576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b60008082805490500361397357600090506139a4565b816001838054905061398591906146ae565b8154811061399657613995614711565b5b906000526020600020015490505b919050565b6000819050919050565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090565b600081519050919050565b600082825260208201905092915050565b60005b83811015613a2b578082015181840152602081019050613a10565b60008484015250505050565b6000601f19601f8301169050919050565b6000613a53826139f1565b613a5d81856139fc565b9350613a6d818560208601613a0d565b613a7681613a37565b840191505092915050565b60006020820190508181036000830152613a9b8184613a48565b905092915050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613ad882613aad565b9050919050565b613ae881613acd565b8114613af357600080fd5b50565b600081359050613b0581613adf565b92915050565b6000819050919050565b613b1e81613b0b565b8114613b2957600080fd5b50565b600081359050613b3b81613b15565b92915050565b60008060408385031215613b5857613b57613aa3565b5b6000613b6685828601613af6565b9250506020613b7785828601613b2c565b9150509250929050565b60008115159050919050565b613b9681613b81565b82525050565b6000602082019050613bb16000830184613b8d565b92915050565b613bc081613b0b565b82525050565b6000602082019050613bdb6000830184613bb7565b92915050565b600080600060608486031215613bfa57613bf9613aa3565b5b6000613c0886828701613af6565b9350506020613c1986828701613af6565b9250506040613c2a86828701613b2c565b9150509250925092565b600060ff82169050919050565b613c4a81613c34565b82525050565b6000602082019050613c656000830184613c41565b92915050565b6000819050919050565b613c7e81613c6b565b82525050565b6000602082019050613c996000830184613c75565b92915050565b600060208284031215613cb557613cb4613aa3565b5b6000613cc384828501613b2c565b91505092915050565b600060208284031215613ce257613ce1613aa3565b5b6000613cf084828501613af6565b91505092915050565b613d0281613acd565b82525050565b6000602082019050613d1d6000830184613cf9565b92915050565b6000613d2e82613acd565b9050919050565b613d3e81613d23565b8114613d4957600080fd5b50565b600081359050613d5b81613d35565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112613d8657613d85613d61565b5b8235905067ffffffffffffffff811115613da357613da2613d66565b5b602083019150836001820283011115613dbf57613dbe613d6b565b5b9250929050565b600080600080600060808688031215613de257613de1613aa3565b5b6000613df088828901613d4c565b9550506020613e0188828901613af6565b9450506040613e1288828901613b2c565b935050606086013567ffffffffffffffff811115613e3357613e32613aa8565b5b613e3f88828901613d70565b92509250509295509295909350565b600063ffffffff82169050919050565b613e6781613e4e565b82525050565b6000602082019050613e826000830184613e5e565b92915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b613ebd81613e88565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613ef881613b0b565b82525050565b6000613f0a8383613eef565b60208301905092915050565b6000602082019050919050565b6000613f2e82613ec3565b613f388185613ece565b9350613f4383613edf565b8060005b83811015613f74578151613f5b8882613efe565b9750613f6683613f16565b925050600181019050613f47565b5085935050505092915050565b600060e082019050613f96600083018a613eb4565b8181036020830152613fa88189613a48565b90508181036040830152613fbc8188613a48565b9050613fcb6060830187613bb7565b613fd86080830186613cf9565b613fe560a0830185613c75565b81810360c0830152613ff78184613f23565b905098975050505050505050565b600065ffffffffffff82169050919050565b61402081614005565b82525050565b600060208201905061403b6000830184614017565b92915050565b61404a81613c34565b811461405557600080fd5b50565b60008135905061406781614041565b92915050565b61407681613c6b565b811461408157600080fd5b50565b6000813590506140938161406d565b92915050565b60008060008060008060c087890312156140b6576140b5613aa3565b5b60006140c489828a01613af6565b96505060206140d589828a01613b2c565b95505060406140e689828a01613b2c565b94505060606140f789828a01614058565b935050608061410889828a01614084565b92505060a061411989828a01614084565b9150509295509295509295565b600080600080600080600060e0888a03121561414557614144613aa3565b5b60006141538a828b01613af6565b97505060206141648a828b01613af6565b96505060406141758a828b01613b2c565b95505060606141868a828b01613b2c565b94505060806141978a828b01614058565b93505060a06141a88a828b01614084565b92505060c06141b98a828b01614084565b91505092959891949750929550565b600080604083850312156141df576141de613aa3565b5b60006141ed85828601613af6565b92505060206141fe85828601613af6565b9150509250929050565b61421181613e4e565b811461421c57600080fd5b50565b60008135905061422e81614208565b92915050565b6000806040838503121561424b5761424a613aa3565b5b600061425985828601613af6565b925050602061426a8582860161421f565b9150509250929050565b61427d81613e4e565b82525050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6142b481614283565b82525050565b6040820160008201516142d06000850182614274565b5060208201516142e360208501826142ab565b50505050565b60006040820190506142fe60008301846142ba565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061434b57607f821691505b60208210810361435e5761435d614304565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061439e82613b0b565b91506143a983613b0b565b92508282019050808211156143c1576143c0614364565b5b92915050565b7f4552433230566f7465733a20667574757265206c6f6f6b757000000000000000600082015250565b60006143fd6019836139fc565b9150614408826143c7565b602082019050919050565b6000602082019050818103600083015261442c816143f0565b9050919050565b7f4552433230566f7465733a2062726f6b656e20636c6f636b206d6f6465000000600082015250565b6000614469601d836139fc565b915061447482614433565b602082019050919050565b600060208201905081810360008301526144988161445c565b9050919050565b7f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60008201527f6178466c6173684c6f616e000000000000000000000000000000000000000000602082015250565b60006144fb602b836139fc565b91506145068261449f565b604082019050919050565b6000602082019050818103600083015261452a816144ee565b9050919050565b600082825260208201905092915050565b82818337600083830152505050565b600061455d8385614531565b935061456a838584614542565b61457383613a37565b840190509392505050565b600060a0820190506145936000830189613cf9565b6145a06020830188613cf9565b6145ad6040830187613bb7565b6145ba6060830186613bb7565b81810360808301526145cd818486614551565b9050979650505050505050565b6000815190506145e98161406d565b92915050565b60006020828403121561460557614604613aa3565b5b6000614613848285016145da565b91505092915050565b7f4552433230466c6173684d696e743a20696e76616c69642072657475726e207660008201527f616c756500000000000000000000000000000000000000000000000000000000602082015250565b60006146786024836139fc565b91506146838261461c565b604082019050919050565b600060208201905081810360008301526146a78161466b565b9050919050565b60006146b982613b0b565b91506146c483613b0b565b92508282039050818111156146dc576146db614364565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b600061479c6025836139fc565b91506147a782614740565b604082019050919050565b600060208201905081810360008301526147cb8161478f565b9050919050565b7f4552433230566f7465733a207369676e61747572652065787069726564000000600082015250565b6000614808601d836139fc565b9150614813826147d2565b602082019050919050565b60006020820190508181036000830152614837816147fb565b9050919050565b60006080820190506148536000830187613c75565b6148606020830186613cf9565b61486d6040830185613bb7565b61487a6060830184613bb7565b95945050505050565b7f4552433230566f7465733a20696e76616c6964206e6f6e636500000000000000600082015250565b60006148b96019836139fc565b91506148c482614883565b602082019050919050565b600060208201905081810360008301526148e8816148ac565b9050919050565b7f45524332305065726d69743a206578706972656420646561646c696e65000000600082015250565b6000614925601d836139fc565b9150614930826148ef565b602082019050919050565b6000602082019050818103600083015261495481614918565b9050919050565b600060c0820190506149706000830189613c75565b61497d6020830188613cf9565b61498a6040830187613cf9565b6149976060830186613bb7565b6149a46080830185613bb7565b6149b160a0830184613bb7565b979650505050505050565b7f45524332305065726d69743a20696e76616c6964207369676e61747572650000600082015250565b60006149f2601e836139fc565b91506149fd826149bc565b602082019050919050565b60006020820190508181036000830152614a21816149e5565b9050919050565b7f4552433230466c6173684d696e743a2077726f6e6720746f6b656e0000000000600082015250565b6000614a5e601b836139fc565b9150614a6982614a28565b602082019050919050565b60006020820190508181036000830152614a8d81614a51565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614af06026836139fc565b9150614afb82614a94565b604082019050919050565b60006020820190508181036000830152614b1f81614ae3565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614b887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614b4b565b614b928683614b4b565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614bcf614bca614bc584613b0b565b614baa565b613b0b565b9050919050565b6000819050919050565b614be983614bb4565b614bfd614bf582614bd6565b848454614b58565b825550505050565b600090565b614c12614c05565b614c1d818484614be0565b505050565b5b81811015614c4157614c36600082614c0a565b600181019050614c23565b5050565b601f821115614c8657614c5781614b26565b614c6084614b3b565b81016020851015614c6f578190505b614c83614c7b85614b3b565b830182614c22565b50505b505050565b600082821c905092915050565b6000614ca960001984600802614c8b565b1980831691505092915050565b6000614cc28383614c98565b9150826002028217905092915050565b614cdb826139f1565b67ffffffffffffffff811115614cf457614cf36146e2565b5b614cfe8254614333565b614d09828285614c45565b600060209050601f831160018114614d3c5760008415614d2a578287015190505b614d348582614cb6565b865550614d9c565b601f198416614d4a86614b26565b60005b82811015614d7257848901518255600182019150602085019450602081019050614d4d565b86831015614d8f5784890151614d8b601f891682614c98565b8355505b6001600288020188555050505b505050505050565b7f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60008201527f766572666c6f77696e6720766f74657300000000000000000000000000000000602082015250565b6000614e006030836139fc565b9150614e0b82614da4565b604082019050919050565b60006020820190508181036000830152614e2f81614df3565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b6000614e6c601f836139fc565b9150614e7782614e36565b602082019050919050565b60006020820190508181036000830152614e9b81614e5f565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203260008201527f3234206269747300000000000000000000000000000000000000000000000000602082015250565b6000614efe6027836139fc565b9150614f0982614ea2565b604082019050919050565b60006020820190508181036000830152614f2d81614ef1565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203360008201527f3220626974730000000000000000000000000000000000000000000000000000602082015250565b6000614f906026836139fc565b9150614f9b82614f34565b604082019050919050565b60006020820190508181036000830152614fbf81614f83565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203460008201527f3820626974730000000000000000000000000000000000000000000000000000602082015250565b60006150226026836139fc565b915061502d82614fc6565b604082019050919050565b6000602082019050818103600083015261505181615015565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006150b46024836139fc565b91506150bf82615058565b604082019050919050565b600060208201905081810360008301526150e3816150a7565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b60006151466022836139fc565b9150615151826150ea565b604082019050919050565b6000602082019050818103600083015261517581615139565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b60006151b2601d836139fc565b91506151bd8261517c565b602082019050919050565b600060208201905081810360008301526151e1816151a5565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006152446025836139fc565b915061524f826151e8565b604082019050919050565b6000602082019050818103600083015261527381615237565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b60006152d66023836139fc565b91506152e18261527a565b604082019050919050565b60006020820190508181036000830152615305816152c9565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b60006153686026836139fc565b91506153738261530c565b604082019050919050565b600060208201905081810360008301526153978161535b565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006153d46020836139fc565b91506153df8261539e565b602082019050919050565b60006020820190508181036000830152615403816153c7565b9050919050565b7f4552433230536e617073686f743a206964206973203000000000000000000000600082015250565b60006154406016836139fc565b915061544b8261540a565b602082019050919050565b6000602082019050818103600083015261546f81615433565b9050919050565b7f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000600082015250565b60006154ac601d836139fc565b91506154b782615476565b602082019050919050565b600060208201905081810360008301526154db8161549f565b9050919050565b600081519050919050565b6000819050602082019050919050565b60006155098251613c6b565b80915050919050565b600061551d826154e2565b82615527846154ed565b9050615532816154fd565b925060208210156155725761556d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802614b4b565b831692505b5050919050565b600060408201905061558e6000830185613bb7565b61559b6020830184613bb7565b9392505050565b600060a0820190506155b76000830188613c75565b6155c46020830187613c75565b6155d16040830186613c75565b6155de6060830185613bb7565b6155eb6080830184613cf9565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061562f82613b0b565b915061563a83613b0b565b92508261564a576156496155f5565b5b828204905092915050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b600061568b6014836139fc565b915061569682615655565b602082019050919050565b600060208201905081810360008301526156ba8161567e565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b60006156f76010836139fc565b9150615702826156c1565b602082019050919050565b60006020820190508181036000830152615726816156ea565b9050919050565b60006080820190506157426000830187613c75565b61574f6020830186613c41565b61575c6040830185613c75565b6157696060830184613c75565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b60006157d76018836139fc565b91506157e2826157a1565b602082019050919050565b60006020820190508181036000830152615806816157ca565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615843601f836139fc565b915061584e8261580d565b602082019050919050565b6000602082019050818103600083015261587281615836565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b60006158d56022836139fc565b91506158e082615879565b604082019050919050565b60006020820190508181036000830152615904816158c8565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b60006159676021836139fc565b91506159728261590b565b604082019050919050565b600060208201905081810360008301526159968161595a565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b60006159f96022836139fc565b9150615a048261599d565b604082019050919050565b60006020820190508181036000830152615a28816159ec565b905091905056fea26469706673582212201e3a95ac0ea6e47958a92f595fe6c769b6cfaf49b623370daaaf649523da853e64736f6c63430008120033

Deployed Bytecode Sourcemap

143749:1489:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103596:100;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105956:201;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104725:108;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;106737:261;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104567:93;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122204:115;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107407:238;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;126076:251;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;144251:65;;;:::i;:::-;;144324:95;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;143087:91;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124613:258;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;138643:266;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;125427:128;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;128950:114;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;94193:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118431:959;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;115517:178;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;125183:151;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104896:127;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;97051:103;;;:::i;:::-;;143497:164;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;121946:128;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;144182:61;;;:::i;:::-;;86915:657;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;96410:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;126599:242;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124375:120;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103815:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;144107:67;;;:::i;:::-;;139013:234;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;125639:248;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108148:436;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105229:193;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;129146:591;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;121235:645;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;116071:219;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105485:151;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124953:150;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;97309:201;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;103596:100;103650:13;103683:5;103676:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103596:100;:::o;105956:201::-;106039:4;106056:13;106072:12;:10;:12::i;:::-;106056:28;;106095:32;106104:5;106111:7;106120:6;106095:8;:32::i;:::-;106145:4;106138:11;;;105956:201;;;;:::o;104725:108::-;104786:7;104813:12;;104806:19;;104725:108;:::o;106737:261::-;106834:4;106851:15;106869:12;:10;:12::i;:::-;106851:30;;106892:38;106908:4;106914:7;106923:6;106892:15;:38::i;:::-;106941:27;106951:4;106957:2;106961:6;106941:9;:27::i;:::-;106986:4;106979:11;;;106737:261;;;;;:::o;104567:93::-;104625:5;104650:2;104643:9;;104567:93;:::o;122204:115::-;122264:7;122291:20;:18;:20::i;:::-;122284:27;;122204:115;:::o;107407:238::-;107495:4;107512:13;107528:12;:10;:12::i;:::-;107512:28;;107551:64;107560:5;107567:7;107604:10;107576:25;107586:5;107593:7;107576:9;:25::i;:::-;:38;;;;:::i;:::-;107551:8;:64::i;:::-;107633:4;107626:11;;;107407:238;;;;:::o;126076:251::-;126172:7;126212;:5;:7::i;:::-;126200:19;;:9;:19;126192:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;126267:52;126286:12;:21;126299:7;126286:21;;;;;;;;;;;;;;;126309:9;126267:18;:52::i;:::-;126260:59;;126076:251;;;;:::o;144251:65::-;96296:13;:11;:13::i;:::-;144298:10:::1;:8;:10::i;:::-;144251:65::o:0;144324:95::-;96296:13;:11;:13::i;:::-;144394:17:::1;144400:2;144404:6;144394:5;:17::i;:::-;144324:95:::0;;:::o;143087:91::-;143143:27;143149:12;:10;:12::i;:::-;143163:6;143143:5;:27::i;:::-;143087:91;:::o;124613:258::-;124673:13;124768:12;124757:7;:5;:7::i;:::-;:23;;;124749:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;124825:38;;;;;;;;;;;;;;;;;;;124613:258;:::o;138643:266::-;138730:7;138751:16;138769:13;138786:55;138795:10;138807:24;:33;138832:7;138807:33;;;;;;;;;;;;;;;138786:8;:55::i;:::-;138750:91;;;;138861:11;:40;;138883:18;138893:7;138883:9;:18::i;:::-;138861:40;;;138875:5;138861:40;138854:47;;;;138643:266;;;;:::o;125427:128::-;125501:7;125528:10;:19;125539:7;125528:19;;;;;;;;;;;;;;;;;;;;;;;;;125521:26;;125427:128;;;:::o;128950:114::-;129022:34;129032:12;:10;:12::i;:::-;129046:9;129022;:34::i;:::-;128950:114;:::o;94193:86::-;94240:4;94264:7;;;;;;;;;;;94257:14;;94193:86;:::o;118431:959::-;118610:4;118645:19;118658:5;118645:12;:19::i;:::-;118635:6;:29;;118627:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;118723:11;118737:23;118746:5;118753:6;118737:8;:23::i;:::-;118723:37;;118771:32;118785:8;118796:6;118771:5;:32::i;:::-;115254:45;118836:8;:20;;;118857:10;118869:5;118876:6;118884:3;118889:4;;118836:58;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:75;118814:161;;;;;;;;;;;;:::i;:::-;;;;;;;;;118986:24;119013:19;:17;:19::i;:::-;118986:46;;119043:63;119067:8;119086:4;119102:3;119093:6;:12;;;;:::i;:::-;119043:15;:63::i;:::-;119128:1;119121:3;:8;:42;;;;119161:1;119133:30;;:16;:30;;;119121:42;119117:244;;;119180:38;119194:8;119214:3;119205:6;:12;;;;:::i;:::-;119180:5;:38::i;:::-;119117:244;;;119251:32;119265:8;119276:6;119251:5;:32::i;:::-;119298:51;119316:8;119327:16;119345:3;119298:9;:51::i;:::-;119117:244;119378:4;119371:11;;;;118431:959;;;;;;;:::o;115517:178::-;115592:7;115636:4;115619:22;;:5;:22;;;:68;;115686:1;115619:68;;;115664:19;:17;:19::i;:::-;115644:17;:39;;;;:::i;:::-;115619:68;115612:75;;115517:178;;;:::o;125183:151::-;125253:6;125279:47;125297:12;:21;125310:7;125297:21;;;;;;;;;;;;;;;:28;;;;125279:17;:47::i;:::-;125272:54;;125183:151;;;:::o;104896:127::-;104970:7;104997:9;:18;105007:7;104997:18;;;;;;;;;;;;;;;;104990:25;;104896:127;;;:::o;97051:103::-;96296:13;:11;:13::i;:::-;97116:30:::1;97143:1;97116:18;:30::i;:::-;97051:103::o:0;143497:164::-;143574:46;143590:7;143599:12;:10;:12::i;:::-;143613:6;143574:15;:46::i;:::-;143631:22;143637:7;143646:6;143631:5;:22::i;:::-;143497:164;;:::o;121946:128::-;122015:7;122042:24;:7;:14;122050:5;122042:14;;;;;;;;;;;;;;;:22;:24::i;:::-;122035:31;;121946:128;;;:::o;144182:61::-;96296:13;:11;:13::i;:::-;144227:8:::1;:6;:8::i;:::-;144182:61::o:0;86915:657::-;87036:13;87064:18;87097:21;87133:15;87163:25;87203:12;87230:27;87338:41;87365:13;87338:5;:26;;:41;;;;:::i;:::-;87394:47;87424:16;87394:8;:29;;:47;;;;:::i;:::-;87456:13;87492:4;87520:1;87512:10;;87551:1;87537:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87285:279;;;;;;;;;;;;;;;;;;;;;86915:657;;;;;;;:::o;96410:87::-;96456:7;96483:6;;;;;;;;;;;96476:13;;96410:87;:::o;126599:242::-;126684:7;126724;:5;:7::i;:::-;126712:19;;:9;:19;126704:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;126779:54;126798:23;126823:9;126779:18;:54::i;:::-;126772:61;;126599:242;;;:::o;124375:120::-;124430:6;124456:31;124474:12;124456:17;:31::i;:::-;124449:38;;124375:120;:::o;103815:104::-;103871:13;103904:7;103897:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103815:104;:::o;144107:67::-;96296:13;:11;:13::i;:::-;144155:11:::1;:9;:11::i;:::-;;144107:67::o:0;139013:234::-;139085:7;139106:16;139124:13;139141:43;139150:10;139162:21;139141:8;:43::i;:::-;139105:79;;;;139204:11;:35;;139226:13;:11;:13::i;:::-;139204:35;;;139218:5;139204:35;139197:42;;;;139013:234;;;:::o;125639:248::-;125712:7;125732:11;125746:12;:21;125759:7;125746:21;;;;;;;;;;;;;;;:28;;;;125732:42;;125824:1;125817:3;:8;:51;;125832:12;:21;125845:7;125832:21;;;;;;;;;;;;;;;125860:1;125854:3;:7;125832:30;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;;;;;;;;;125817:51;;;125828:1;125817:51;125810:58;;;;;125639:248;;;:::o;108148:436::-;108241:4;108258:13;108274:12;:10;:12::i;:::-;108258:28;;108297:24;108324:25;108334:5;108341:7;108324:9;:25::i;:::-;108297:52;;108388:15;108368:16;:35;;108360:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;108481:60;108490:5;108497:7;108525:15;108506:16;:34;108481:8;:60::i;:::-;108572:4;108565:11;;;;108148:436;;;;:::o;105229:193::-;105308:4;105325:13;105341:12;:10;:12::i;:::-;105325:28;;105364;105374:5;105381:2;105385:6;105364:9;:28::i;:::-;105410:4;105403:11;;;105229:193;;;;:::o;129146:591::-;129373:6;129354:15;:25;;129346:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;129424:14;129441:174;129469:87;123988:71;129529:9;129540:5;129547:6;129496:58;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;129486:69;;;;;;129469:16;:87::i;:::-;129571:1;129587;129603;129441:13;:174::i;:::-;129424:191;;129643:17;129653:6;129643:9;:17::i;:::-;129634:5;:26;129626:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;129701:28;129711:6;129719:9;129701;:28::i;:::-;129335:402;129146:591;;;;;;:::o;121235:645::-;121479:8;121460:15;:27;;121452:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;121534:18;120410:95;121594:5;121601:7;121610:5;121617:16;121627:5;121617:9;:16::i;:::-;121635:8;121565:79;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;121555:90;;;;;;121534:111;;121658:12;121673:28;121690:10;121673:16;:28::i;:::-;121658:43;;121714:14;121731:28;121745:4;121751:1;121754;121757;121731:13;:28::i;:::-;121714:45;;121788:5;121778:15;;:6;:15;;;121770:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;121841:31;121850:5;121857:7;121866:5;121841:8;:31::i;:::-;121441:439;;;121235:645;;;;;;;:::o;116071:219::-;116158:7;116203:4;116186:22;;:5;:22;;;116178:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;116258:24;116268:5;116275:6;116258:9;:24::i;:::-;116251:31;;116071:219;;;;:::o;105485:151::-;105574:7;105601:11;:18;105613:5;105601:18;;;;;;;;;;;;;;;:27;105620:7;105601:27;;;;;;;;;;;;;;;;105594:34;;105485:151;;;;:::o;124953:150::-;125032:17;;:::i;:::-;125069:12;:21;125082:7;125069:21;;;;;;;;;;;;;;;125091:3;125069:26;;;;;;;;;;:::i;:::-;;;;;;;;;125062:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124953:150;;;;:::o;97309:201::-;96296:13;:11;:13::i;:::-;97418:1:::1;97398:22;;:8;:22;;::::0;97390:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;97474:28;97493:8;97474:18;:28::i;:::-;97309:201:::0;:::o;80407:348::-;80503:11;80553:2;80537:5;80531:19;:24;80527:221;;;80579:20;80593:5;80579:13;:20::i;:::-;80572:27;;;;80527:221;80673:5;80632:32;80658:5;80632:25;:32::i;:::-;:38;;:46;;;;;;:::i;:::-;;78836:66;80717:18;;80693:43;;80407:348;;;;;:::o;76600:207::-;76668:20;76779:10;76769:20;;76600:207;;;:::o;130043:290::-;130128:28;130140:7;130149:6;130128:11;:28::i;:::-;130192:12;:10;:12::i;:::-;130175:29;;:13;:11;:13::i;:::-;:29;;130167:90;;;;;;;;;;;;:::i;:::-;;;;;;;;;130270:55;130287:23;130312:4;130318:6;130270:16;:55::i;:::-;;;130043:290;;:::o;110147:548::-;110250:1;110231:21;;:7;:21;;;110223:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;110301:49;110330:1;110334:7;110343:6;110301:20;:49::i;:::-;110379:6;110363:12;;:22;;;;;;;:::i;:::-;;;;;;;;110556:6;110534:9;:18;110544:7;110534:18;;;;;;;;;;;;;;;;:28;;;;;;;;;;;110610:7;110589:37;;110606:1;110589:37;;;110619:6;110589:37;;;;;;:::i;:::-;;;;;;;;110639:48;110667:1;110671:7;110680:6;110639:19;:48::i;:::-;110147:548;;:::o;132982:98::-;133040:7;133071:1;133067;:5;;;;:::i;:::-;133060:12;;132982:98;;;;:::o;5434:195::-;5491:7;5528:17;5519:26;;:5;:26;;5511:78;;;;;;;;;;;;:::i;:::-;;;;;;;;;5615:5;5600:21;;5434:195;;;:::o;18270:190::-;18326:6;18362:16;18353:25;;:5;:25;;18345:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;18446:5;18432:20;;18270:190;;;:::o;139464:588::-;139573:44;139600:4;139606:2;139610:6;139573:26;:44::i;:::-;139650:1;139634:18;;:4;:18;;;139630:415;;139690:26;139713:2;139690:22;:26::i;:::-;139731:28;:26;:28::i;:::-;139630:415;;;139795:1;139781:16;;:2;:16;;;139777:268;;139835:28;139858:4;139835:22;:28::i;:::-;139878;:26;:28::i;:::-;139777:268;;;139964:28;139987:4;139964:22;:28::i;:::-;140007:26;140030:2;140007:22;:26::i;:::-;139777:268;139630:415;139464:588;;;:::o;130768:228::-;130876:43;130902:4;130908:2;130912:6;130876:25;:43::i;:::-;130932:56;130949:15;130959:4;130949:9;:15::i;:::-;130966:13;130976:2;130966:9;:13::i;:::-;130981:6;130932:16;:56::i;:::-;130768:228;;;:::o;17212:190::-;17268:6;17304:16;17295:25;;:5;:25;;17287:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;17388:5;17374:20;;17212:190;;;:::o;113797:91::-;;;;:::o;114492:90::-;;;;:::o;133088:103::-;133151:7;133182:1;133178;:5;;;;:::i;:::-;133171:12;;133088:103;;;;:::o;47218:114::-;47283:7;47310;:14;;;47303:21;;47218:114;;;:::o;92306:98::-;92359:7;92386:10;92379:17;;92306:98;:::o;112141:346::-;112260:1;112243:19;;:5;:19;;;112235:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;112341:1;112322:21;;:7;:21;;;112314:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;112425:6;112395:11;:18;112407:5;112395:18;;;;;;;;;;;;;;;:27;112414:7;112395:27;;;;;;;;;;;;;;;:36;;;;112463:7;112447:32;;112456:5;112447:32;;;112472:6;112447:32;;;;;;:::i;:::-;;;;;;;;112141:346;;;:::o;112778:419::-;112879:24;112906:25;112916:5;112923:7;112906:9;:25::i;:::-;112879:52;;112966:17;112946:16;:37;112942:248;;113028:6;113008:16;:26;;113000:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;113112:51;113121:5;113128:7;113156:6;113137:16;:25;113112:8;:51::i;:::-;112942:248;112868:329;112778:419;;;:::o;109054:806::-;109167:1;109151:18;;:4;:18;;;109143:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;109244:1;109230:16;;:2;:16;;;109222:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;109299:38;109320:4;109326:2;109330:6;109299:20;:38::i;:::-;109350:19;109372:9;:15;109382:4;109372:15;;;;;;;;;;;;;;;;109350:37;;109421:6;109406:11;:21;;109398:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;109538:6;109524:11;:20;109506:9;:15;109516:4;109506:15;;;;;;;;;;;;;;;:38;;;;109741:6;109724:9;:13;109734:2;109724:13;;;;;;;;;;;;;;;;:23;;;;;;;;;;;109791:2;109776:26;;109785:4;109776:26;;;109795:6;109776:26;;;;;;:::i;:::-;;;;;;;;109815:37;109835:4;109841:2;109845:6;109815:19;:37::i;:::-;109132:728;109054:806;;;:::o;85553:268::-;85606:7;85647:11;85630:28;;85638:4;85630:28;;;:63;;;;;85679:14;85662:13;:31;85630:63;85626:188;;;85717:22;85710:29;;;;85626:188;85779:23;:21;:23::i;:::-;85772:30;;85553:268;;:::o;126930:1934::-;127027:7;128137:14;128154:5;:12;;;;128137:29;;128179:11;128205:12;128220:6;128205:21;;128252:1;128243:6;:10;128239:249;;;128270:11;128293:17;128303:6;128293:9;:17::i;:::-;128284:6;:26;;;;:::i;:::-;128270:40;;128367:9;128329:25;128343:5;128350:3;128329:13;:25::i;:::-;:35;;;;;;;;;;;;:47;;;128325:152;;;128404:3;128397:10;;128325:152;;;128460:1;128454:3;:7;;;;:::i;:::-;128448:13;;128325:152;128255:233;128239:249;128500;128513:4;128507:3;:10;128500:249;;;128534:11;128548:23;128561:3;128566:4;128548:12;:23::i;:::-;128534:37;;128628:9;128590:25;128604:5;128611:3;128590:13;:25::i;:::-;:35;;;;;;;;;;;;:47;;;128586:152;;;128665:3;128658:10;;128586:152;;;128721:1;128715:3;:7;;;;:::i;:::-;128709:13;;128586:152;128519:230;128500:249;;;128801:1;128793:4;:9;:52;;128809:30;128823:5;128837:1;128830:4;:8;128809:13;:30::i;:::-;:36;;;;;;;;;;;;128793:52;;;128805:1;128793:52;128786:59;;;;;;;126930:1934;;;;:::o;96575:132::-;96650:12;:10;:12::i;:::-;96639:23;;:7;:5;:7::i;:::-;:23;;;96631:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;96575:132::o;95048:120::-;94057:16;:14;:16::i;:::-;95117:5:::1;95107:7;;:15;;;;;;;;;;;;;;;;;;95138:22;95147:12;:10;:12::i;:::-;95138:22;;;;;;:::i;:::-;;;;;;;;95048:120::o:0;144927:145::-;145041:23;145053:2;145057:6;145041:11;:23::i;:::-;144927:145;;:::o;145080:155::-;145199:28;145211:7;145220:6;145199:11;:28::i;:::-;145080:155;;:::o;140060:1619::-;140149:4;140155:7;140196:1;140183:10;:14;140175:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;140257:23;:21;:23::i;:::-;140243:10;:37;;140235:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;141453:13;141469:40;141498:10;141469:9;:13;;:28;;:40;;;;:::i;:::-;141453:56;;141535:9;:13;;:20;;;;141526:5;:29;141522:150;;141580:5;141587:1;141572:17;;;;;;;141522:150;141630:4;141636:9;:16;;141653:5;141636:23;;;;;;;;:::i;:::-;;;;;;;;;;141622:38;;;;;140060:1619;;;;;;:::o;131174:388::-;131259:23;131285:20;131295:9;131285;:20::i;:::-;131259:46;;131316:24;131343:20;131353:9;131343;:20::i;:::-;131316:47;;131398:9;131374:10;:21;131385:9;131374:21;;;;;;;;;;;;;;;;:33;;;;;;;;;;;;;;;;;;131469:9;131425:54;;131452:15;131425:54;;131441:9;131425:54;;;;;;;;;;;;131492:62;131509:15;131526:9;131537:16;131492;:62::i;:::-;131248:314;;131174:388;;:::o;117250:105::-;117310:7;117250:105;:::o;97670:191::-;97744:16;97763:6;;;;;;;;;;;97744:25;;97789:8;97780:6;;:17;;;;;;;;;;;;;;;;;;97844:8;97813:40;;97834:8;97813:40;;;;;;;;;;;;97733:128;97670:191;:::o;94789:118::-;93798:19;:17;:19::i;:::-;94859:4:::1;94849:7;;:14;;;;;;;;;;;;;;;;;;94879:20;94886:12;:10;:12::i;:::-;94879:20;;;;;;:::i;:::-;;;;;;;;94789:118::o:0;80891:274::-;80985:13;78836:66;81044:18;;81034:5;81015:47;81011:147;;81086:15;81095:5;81086:8;:15::i;:::-;81079:22;;;;81011:147;81141:5;81134:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80891:274;;;;;:::o;138115:223::-;138162:7;138182:30;:18;:28;:30::i;:::-;138225:17;138245:23;:21;:23::i;:::-;138225:43;;138284:19;138293:9;138284:19;;;;;;:::i;:::-;;;;;;;;138321:9;138314:16;;;138115:223;:::o;86653:167::-;86730:7;86757:55;86779:20;:18;:20::i;:::-;86801:10;86757:21;:55::i;:::-;86750:62;;86653:167;;;:::o;70550:236::-;70635:7;70656:17;70675:18;70697:25;70708:4;70714:1;70717;70720;70697:10;:25::i;:::-;70655:67;;;;70733:18;70745:5;70733:11;:18::i;:::-;70769:9;70762:16;;;;70550:236;;;;;;:::o;122457:207::-;122517:15;122545:30;122578:7;:14;122586:5;122578:14;;;;;;;;;;;;;;;122545:47;;122613:15;:5;:13;:15::i;:::-;122603:25;;122639:17;:5;:15;:17::i;:::-;122534:130;122457:207;;;:::o;116689:234::-;116770:7;116689:234;;;;:::o;79164:292::-;79229:11;79253:17;79279:3;79253:30;;79312:2;79298:4;:11;:16;79294:74;;;79352:3;79338:18;;;;;;;;;;;:::i;:::-;;;;;;;;79294:74;79435:4;:11;79426:4;79418:13;;;:::i;:::-;79410:22;;:36;79402:45;;79378:70;;;79164:292;;;:::o;129844:105::-;129897:7;129924:17;129917:24;;129844:105;:::o;132187:787::-;132361:17;132380;132410:11;132424:5;:12;;;;132410:26;;132474:25;132509:1;132502:3;:8;:59;;132532:29;132546:5;132559:1;132553:3;:7;132532:13;:29::i;:::-;132502:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132513:16;;;;;;;;132524:1;132513:16;;;;;;132527:1;132513:16;;;;;132502:59;132474:87;;132590:7;:13;;;132578:25;;;;132630:20;132633:9;132644:5;132630:2;:20;;:::i;:::-;132618:32;;132677:1;132671:3;:7;:39;;;;;132703:7;:5;:7::i;:::-;132682:28;;:7;:17;;;:28;;;132671:39;132667:289;;;132769:29;132788:9;132769:18;:29::i;:::-;132731;132745:5;132758:1;132752:3;:7;132731:13;:29::i;:::-;:35;;;:67;;;;;;;;;;;;;;;;;;132667:289;;;132839:5;132850:89;;;;;;;;132873:26;132891:7;:5;:7::i;:::-;132873:26;;:17;:26::i;:::-;132850:89;;;;;;132908:29;132927:9;132908:18;:29::i;:::-;132850:89;;;;;132839:101;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132667:289;132449:518;132399:575;132187:787;;;;;;:::o;144427:221::-;93798:19;:17;:19::i;:::-;144596:44:::1;144623:4;144629:2;144633:6;144596:26;:44::i;:::-;144427:221:::0;;;:::o;144726:193::-;144868:43;144894:4;144900:2;144904:6;144868:25;:43::i;:::-;144726:193;;;:::o;141687:146::-;141755:70;141771:24;:33;141796:7;141771:33;;;;;;;;;;;;;;;141806:18;141816:7;141806:9;:18::i;:::-;141755:15;:70::i;:::-;141687:146;:::o;141841:118::-;141898:53;141914:21;141937:13;:11;:13::i;:::-;141898:15;:53::i;:::-;141841:118::o;131570:609::-;131668:3;131661:10;;:3;:10;;;;:24;;;;;131684:1;131675:6;:10;131661:24;131657:515;;;131721:1;131706:17;;:3;:17;;;131702:224;;131745:17;131764;131785:54;131802:12;:17;131815:3;131802:17;;;;;;;;;;;;;;;131821:9;131832:6;131785:16;:54::i;:::-;131744:95;;;;131884:3;131863:47;;;131889:9;131900;131863:47;;;;;;;:::i;:::-;;;;;;;;131725:201;;131702:224;131961:1;131946:17;;:3;:17;;;131942:219;;131985:17;132004;132025:49;132042:12;:17;132055:3;132042:17;;;;;;;;;;;;;;;132061:4;132067:6;132025:16;:49::i;:::-;131984:90;;;;132119:3;132098:47;;;132124:9;132135;132098:47;;;;;;;:::i;:::-;;;;;;;;131965:196;;131942:219;131657:515;131570:609;;;:::o;85829:182::-;85884:7;83745:95;85944:11;85957:14;85973:13;85996:4;85921:81;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;85911:92;;;;;;85904:99;;85829:182;:::o;54517:1673::-;54565:7;54594:1;54589;:6;54585:47;;54619:1;54612:8;;;;54585:47;55323:14;55357:1;55346:7;55351:1;55346:4;:7::i;:::-;:12;;55340:1;:19;;55323:36;;55825:1;55814:6;55810:1;:10;;;;;:::i;:::-;;;55801:6;:19;55800:26;;55791:35;;55875:1;55864:6;55860:1;:10;;;;;:::i;:::-;;;55851:6;:19;55850:26;;55841:35;;55925:1;55914:6;55910:1;:10;;;;;:::i;:::-;;;55901:6;:19;55900:26;;55891:35;;55975:1;55964:6;55960:1;:10;;;;;:::i;:::-;;;55951:6;:19;55950:26;;55941:35;;56025:1;56014:6;56010:1;:10;;;;;:::i;:::-;;;56001:6;:19;56000:26;;55991:35;;56075:1;56064:6;56060:1;:10;;;;;:::i;:::-;;;56051:6;:19;56050:26;;56041:35;;56125:1;56114:6;56110:1;:10;;;;;:::i;:::-;;;56101:6;:19;56100:26;;56091:35;;56148:23;56152:6;56164;56160:1;:10;;;;;:::i;:::-;;;56148:3;:23::i;:::-;56141:30;;;54517:1673;;;;:::o;133339:244::-;133425:25;133497:10;133494:1;133487:21;133561:3;133554:4;133551:1;133541:18;133537:28;133522:43;;133339:244;;;;:::o;48674:156::-;48736:7;48821:1;48816;48812;:5;48811:11;;;;:::i;:::-;48806:1;48802;:5;48801:21;;;;:::i;:::-;48794:28;;48674:156;;;;:::o;94537:108::-;94604:8;:6;:8::i;:::-;94596:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;94537:108::o;130427:194::-;130512:28;130524:7;130533:6;130512:11;:28::i;:::-;130553:60;130570:23;130595:9;130606:6;130553:16;:60::i;:::-;;;130427:194;;:::o;138404:127::-;138468:7;138495:28;:18;:26;:28::i;:::-;138488:35;;138404:127;:::o;88283:958::-;88372:7;88412:1;88396:5;:12;;;;:17;88392:58;;88437:1;88430:8;;;;88392:58;88462:11;88488:12;88503:5;:12;;;;88488:27;;88528:444;88541:4;88535:3;:10;88528:444;;;88562:11;88576:23;88589:3;88594:4;88576:12;:23::i;:::-;88562:37;;88853:7;88820:24;88833:5;88840:3;88820:12;:24::i;:::-;:30;;;:40;88816:145;;;88888:3;88881:10;;88816:145;;;88944:1;88938:3;:7;;;;:::i;:::-;88932:13;;88816:145;88547:425;88528:444;;;89098:1;89092:3;:7;:56;;;;;89141:7;89103:28;89116:5;89129:1;89123:3;:7;;;;:::i;:::-;89103:12;:28::i;:::-;:34;;;:45;89092:56;89088:146;;;89178:1;89172:3;:7;;;;:::i;:::-;89165:14;;;;;;89088:146;89219:3;89212:10;;;;88283:958;;;;;:::o;94352:108::-;94423:8;:6;:8::i;:::-;94422:9;94414:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;94352:108::o;79545:415::-;79604:13;79630:11;79644:16;79655:4;79644:10;:16::i;:::-;79630:30;;79750:17;79781:2;79770:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79750:34;;79875:3;79870;79863:16;79916:4;79909;79904:3;79900:14;79893:28;79949:3;79942:10;;;;79545:415;;;:::o;47340:127::-;47447:1;47429:7;:14;;;:19;;;;;;;;;;;47340:127;:::o;72334:406::-;72427:12;72537:4;72531:11;72568:10;72563:3;72556:23;72616:15;72609:4;72604:3;72600:14;72593:39;72669:10;72662:4;72657:3;72653:14;72646:34;72717:4;72712:3;72702:20;72694:28;;72505:228;72334:406;;;;:::o;68934:1477::-;69022:7;69031:12;69956:66;69951:1;69943:10;;:79;69939:163;;;70055:1;70059:30;70039:51;;;;;;69939:163;70199:14;70216:24;70226:4;70232:1;70235;70238;70216:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70199:41;;70273:1;70255:20;;:6;:20;;;70251:103;;70308:1;70312:29;70292:50;;;;;;;70251:103;70374:6;70382:20;70366:37;;;;;68934:1477;;;;;;;;:::o;64394:521::-;64472:20;64463:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;64459:449;64509:7;64459:449;64570:29;64561:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;64557:351;;64616:34;;;;;;;;;;:::i;:::-;;;;;;;;64557:351;64681:35;64672:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;64668:240;;64733:41;;;;;;;;;;:::i;:::-;;;;;;;;64668:240;64805:30;64796:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;64792:116;;64852:44;;;;;;;;;;:::i;:::-;;;;;;;;64792:116;64394:521;;:::o;141967:310::-;142062:17;142082:23;:21;:23::i;:::-;142062:43;;142153:9;142120:30;142136:9;:13;;142120:15;:30::i;:::-;:42;142116:154;;;142179:9;:13;;142198:9;142179:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142223:9;:16;;142245:12;142223:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142116:154;142051:226;141967:310;;:::o;56667:1019::-;56719:7;56739:14;56756:1;56739:18;;56812:1;56806:3;56797:5;:12;;:16;56793:102;;;56844:3;56834:13;;;;;56876:3;56866:13;;;;56793:102;56927:1;56922:2;56913:5;:11;;:15;56909:99;;;56959:2;56949:12;;;;;56990:2;56980:12;;;;56909:99;57040:1;57035:2;57026:5;:11;;:15;57022:99;;;57072:2;57062:12;;;;;57103:2;57093:12;;;;57022:99;57153:1;57148:2;57139:5;:11;;:15;57135:99;;;57185:2;57175:12;;;;;57216:2;57206:12;;;;57135:99;57265:1;57261;57252:5;:10;;:14;57248:96;;;57297:1;57287:11;;;;;57327:1;57317:11;;;;57248:96;57375:1;57371;57362:5;:10;;:14;57358:96;;;57407:1;57397:11;;;;;57437:1;57427:11;;;;57358:96;57485:1;57481;57472:5;:10;;:14;57468:96;;;57517:1;57507:11;;;;;57547:1;57537:11;;;;57468:96;57595:1;57591;57582:5;:10;;:14;57578:66;;;57627:1;57617:11;;;;57578:66;57672:6;57665:13;;;56667:1019;;;:::o;48449:106::-;48507:7;48538:1;48534;:5;:13;;48546:1;48534:13;;;48542:1;48534:13;48527:20;;48449:106;;;;:::o;111028:675::-;111131:1;111112:21;;:7;:21;;;111104:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;111184:49;111205:7;111222:1;111226:6;111184:20;:49::i;:::-;111246:22;111271:9;:18;111281:7;111271:18;;;;;;;;;;;;;;;;111246:43;;111326:6;111308:14;:24;;111300:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;111445:6;111428:14;:23;111407:9;:18;111417:7;111407:18;;;;;;;;;;;;;;;:44;;;;111562:6;111546:12;;:22;;;;;;;;;;;111623:1;111597:37;;111606:7;111597:37;;;111627:6;111597:37;;;;;;:::i;:::-;;;;;;;;111647:48;111667:7;111684:1;111688:6;111647:19;:48::i;:::-;111093:610;111028:675;;:::o;91036:584::-;91117:31;91161:12;91504:8;91501:1;91494:19;91559:3;91552:4;91549:1;91539:18;91535:28;91527:36;;91591:21;:4;:19;:21::i;:::-;91584:28;;;91036:584;;;;:::o;80037:251::-;80098:7;80118:14;80171:4;80162;80135:33;;:40;80118:57;;80199:2;80190:6;:11;80186:71;;;80225:20;;;;;;;;;;;;;;80186:71;80274:6;80267:13;;;80037:251;;;:::o;142285:212::-;142355:7;142393:1;142379:3;:10;;;;:15;142375:115;;142418:1;142411:8;;;;142375:115;142459:3;142476:1;142463:3;:10;;;;:14;;;;:::i;:::-;142459:19;;;;;;;;:::i;:::-;;;;;;;;;;142452:26;;142285:212;;;;:::o;75993:195::-;76054:21;76166:4;76156:14;;75993:195;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;:::o;7:99:1:-;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:169::-;196:11;230:6;225:3;218:19;270:4;265:3;261:14;246:29;;112:169;;;;:::o;287:246::-;368:1;378:113;392:6;389:1;386:13;378:113;;;477:1;472:3;468:11;462:18;458:1;453:3;449:11;442:39;414:2;411:1;407:10;402:15;;378:113;;;525:1;516:6;511:3;507:16;500:27;349:184;287:246;;;:::o;539:102::-;580:6;631:2;627:7;622:2;615:5;611:14;607:28;597:38;;539:102;;;:::o;647:377::-;735:3;763:39;796:5;763:39;:::i;:::-;818:71;882:6;877:3;818:71;:::i;:::-;811:78;;898:65;956:6;951:3;944:4;937:5;933:16;898:65;:::i;:::-;988:29;1010:6;988:29;:::i;:::-;983:3;979:39;972:46;;739:285;647:377;;;;:::o;1030:313::-;1143:4;1181:2;1170:9;1166:18;1158:26;;1230:9;1224:4;1220:20;1216:1;1205:9;1201:17;1194:47;1258:78;1331:4;1322:6;1258:78;:::i;:::-;1250:86;;1030:313;;;;:::o;1430:117::-;1539:1;1536;1529:12;1553:117;1662:1;1659;1652:12;1676:126;1713:7;1753:42;1746:5;1742:54;1731:65;;1676:126;;;:::o;1808:96::-;1845:7;1874:24;1892:5;1874:24;:::i;:::-;1863:35;;1808:96;;;:::o;1910:122::-;1983:24;2001:5;1983:24;:::i;:::-;1976:5;1973:35;1963:63;;2022:1;2019;2012:12;1963:63;1910:122;:::o;2038:139::-;2084:5;2122:6;2109:20;2100:29;;2138:33;2165:5;2138:33;:::i;:::-;2038:139;;;;:::o;2183:77::-;2220:7;2249:5;2238:16;;2183:77;;;:::o;2266:122::-;2339:24;2357:5;2339:24;:::i;:::-;2332:5;2329:35;2319:63;;2378:1;2375;2368:12;2319:63;2266:122;:::o;2394:139::-;2440:5;2478:6;2465:20;2456:29;;2494:33;2521:5;2494:33;:::i;:::-;2394:139;;;;:::o;2539:474::-;2607:6;2615;2664:2;2652:9;2643:7;2639:23;2635:32;2632:119;;;2670:79;;:::i;:::-;2632:119;2790:1;2815:53;2860:7;2851:6;2840:9;2836:22;2815:53;:::i;:::-;2805:63;;2761:117;2917:2;2943:53;2988:7;2979:6;2968:9;2964:22;2943:53;:::i;:::-;2933:63;;2888:118;2539:474;;;;;:::o;3019:90::-;3053:7;3096:5;3089:13;3082:21;3071:32;;3019:90;;;:::o;3115:109::-;3196:21;3211:5;3196:21;:::i;:::-;3191:3;3184:34;3115:109;;:::o;3230:210::-;3317:4;3355:2;3344:9;3340:18;3332:26;;3368:65;3430:1;3419:9;3415:17;3406:6;3368:65;:::i;:::-;3230:210;;;;:::o;3446:118::-;3533:24;3551:5;3533:24;:::i;:::-;3528:3;3521:37;3446:118;;:::o;3570:222::-;3663:4;3701:2;3690:9;3686:18;3678:26;;3714:71;3782:1;3771:9;3767:17;3758:6;3714:71;:::i;:::-;3570:222;;;;:::o;3798:619::-;3875:6;3883;3891;3940:2;3928:9;3919:7;3915:23;3911:32;3908:119;;;3946:79;;:::i;:::-;3908:119;4066:1;4091:53;4136:7;4127:6;4116:9;4112:22;4091:53;:::i;:::-;4081:63;;4037:117;4193:2;4219:53;4264:7;4255:6;4244:9;4240:22;4219:53;:::i;:::-;4209:63;;4164:118;4321:2;4347:53;4392:7;4383:6;4372:9;4368:22;4347:53;:::i;:::-;4337:63;;4292:118;3798:619;;;;;:::o;4423:86::-;4458:7;4498:4;4491:5;4487:16;4476:27;;4423:86;;;:::o;4515:112::-;4598:22;4614:5;4598:22;:::i;:::-;4593:3;4586:35;4515:112;;:::o;4633:214::-;4722:4;4760:2;4749:9;4745:18;4737:26;;4773:67;4837:1;4826:9;4822:17;4813:6;4773:67;:::i;:::-;4633:214;;;;:::o;4853:77::-;4890:7;4919:5;4908:16;;4853:77;;;:::o;4936:118::-;5023:24;5041:5;5023:24;:::i;:::-;5018:3;5011:37;4936:118;;:::o;5060:222::-;5153:4;5191:2;5180:9;5176:18;5168:26;;5204:71;5272:1;5261:9;5257:17;5248:6;5204:71;:::i;:::-;5060:222;;;;:::o;5288:329::-;5347:6;5396:2;5384:9;5375:7;5371:23;5367:32;5364:119;;;5402:79;;:::i;:::-;5364:119;5522:1;5547:53;5592:7;5583:6;5572:9;5568:22;5547:53;:::i;:::-;5537:63;;5493:117;5288:329;;;;:::o;5623:::-;5682:6;5731:2;5719:9;5710:7;5706:23;5702:32;5699:119;;;5737:79;;:::i;:::-;5699:119;5857:1;5882:53;5927:7;5918:6;5907:9;5903:22;5882:53;:::i;:::-;5872:63;;5828:117;5623:329;;;;:::o;5958:118::-;6045:24;6063:5;6045:24;:::i;:::-;6040:3;6033:37;5958:118;;:::o;6082:222::-;6175:4;6213:2;6202:9;6198:18;6190:26;;6226:71;6294:1;6283:9;6279:17;6270:6;6226:71;:::i;:::-;6082:222;;;;:::o;6310:124::-;6375:7;6404:24;6422:5;6404:24;:::i;:::-;6393:35;;6310:124;;;:::o;6440:178::-;6541:52;6587:5;6541:52;:::i;:::-;6534:5;6531:63;6521:91;;6608:1;6605;6598:12;6521:91;6440:178;:::o;6624:195::-;6698:5;6736:6;6723:20;6714:29;;6752:61;6807:5;6752:61;:::i;:::-;6624:195;;;;:::o;6825:117::-;6934:1;6931;6924:12;6948:117;7057:1;7054;7047:12;7071:117;7180:1;7177;7170:12;7207:552;7264:8;7274:6;7324:3;7317:4;7309:6;7305:17;7301:27;7291:122;;7332:79;;:::i;:::-;7291:122;7445:6;7432:20;7422:30;;7475:18;7467:6;7464:30;7461:117;;;7497:79;;:::i;:::-;7461:117;7611:4;7603:6;7599:17;7587:29;;7665:3;7657:4;7649:6;7645:17;7635:8;7631:32;7628:41;7625:128;;;7672:79;;:::i;:::-;7625:128;7207:552;;;;;:::o;7765:1019::-;7890:6;7898;7906;7914;7922;7971:3;7959:9;7950:7;7946:23;7942:33;7939:120;;;7978:79;;:::i;:::-;7939:120;8098:1;8123:81;8196:7;8187:6;8176:9;8172:22;8123:81;:::i;:::-;8113:91;;8069:145;8253:2;8279:53;8324:7;8315:6;8304:9;8300:22;8279:53;:::i;:::-;8269:63;;8224:118;8381:2;8407:53;8452:7;8443:6;8432:9;8428:22;8407:53;:::i;:::-;8397:63;;8352:118;8537:2;8526:9;8522:18;8509:32;8568:18;8560:6;8557:30;8554:117;;;8590:79;;:::i;:::-;8554:117;8703:64;8759:7;8750:6;8739:9;8735:22;8703:64;:::i;:::-;8685:82;;;;8480:297;7765:1019;;;;;;;;:::o;8790:93::-;8826:7;8866:10;8859:5;8855:22;8844:33;;8790:93;;;:::o;8889:115::-;8974:23;8991:5;8974:23;:::i;:::-;8969:3;8962:36;8889:115;;:::o;9010:218::-;9101:4;9139:2;9128:9;9124:18;9116:26;;9152:69;9218:1;9207:9;9203:17;9194:6;9152:69;:::i;:::-;9010:218;;;;:::o;9234:149::-;9270:7;9310:66;9303:5;9299:78;9288:89;;9234:149;;;:::o;9389:115::-;9474:23;9491:5;9474:23;:::i;:::-;9469:3;9462:36;9389:115;;:::o;9510:114::-;9577:6;9611:5;9605:12;9595:22;;9510:114;;;:::o;9630:184::-;9729:11;9763:6;9758:3;9751:19;9803:4;9798:3;9794:14;9779:29;;9630:184;;;;:::o;9820:132::-;9887:4;9910:3;9902:11;;9940:4;9935:3;9931:14;9923:22;;9820:132;;;:::o;9958:108::-;10035:24;10053:5;10035:24;:::i;:::-;10030:3;10023:37;9958:108;;:::o;10072:179::-;10141:10;10162:46;10204:3;10196:6;10162:46;:::i;:::-;10240:4;10235:3;10231:14;10217:28;;10072:179;;;;:::o;10257:113::-;10327:4;10359;10354:3;10350:14;10342:22;;10257:113;;;:::o;10406:732::-;10525:3;10554:54;10602:5;10554:54;:::i;:::-;10624:86;10703:6;10698:3;10624:86;:::i;:::-;10617:93;;10734:56;10784:5;10734:56;:::i;:::-;10813:7;10844:1;10829:284;10854:6;10851:1;10848:13;10829:284;;;10930:6;10924:13;10957:63;11016:3;11001:13;10957:63;:::i;:::-;10950:70;;11043:60;11096:6;11043:60;:::i;:::-;11033:70;;10889:224;10876:1;10873;10869:9;10864:14;;10829:284;;;10833:14;11129:3;11122:10;;10530:608;;;10406:732;;;;:::o;11144:1215::-;11493:4;11531:3;11520:9;11516:19;11508:27;;11545:69;11611:1;11600:9;11596:17;11587:6;11545:69;:::i;:::-;11661:9;11655:4;11651:20;11646:2;11635:9;11631:18;11624:48;11689:78;11762:4;11753:6;11689:78;:::i;:::-;11681:86;;11814:9;11808:4;11804:20;11799:2;11788:9;11784:18;11777:48;11842:78;11915:4;11906:6;11842:78;:::i;:::-;11834:86;;11930:72;11998:2;11987:9;11983:18;11974:6;11930:72;:::i;:::-;12012:73;12080:3;12069:9;12065:19;12056:6;12012:73;:::i;:::-;12095;12163:3;12152:9;12148:19;12139:6;12095:73;:::i;:::-;12216:9;12210:4;12206:20;12200:3;12189:9;12185:19;12178:49;12244:108;12347:4;12338:6;12244:108;:::i;:::-;12236:116;;11144:1215;;;;;;;;;;:::o;12365:97::-;12401:7;12441:14;12434:5;12430:26;12419:37;;12365:97;;;:::o;12468:115::-;12553:23;12570:5;12553:23;:::i;:::-;12548:3;12541:36;12468:115;;:::o;12589:218::-;12680:4;12718:2;12707:9;12703:18;12695:26;;12731:69;12797:1;12786:9;12782:17;12773:6;12731:69;:::i;:::-;12589:218;;;;:::o;12813:118::-;12884:22;12900:5;12884:22;:::i;:::-;12877:5;12874:33;12864:61;;12921:1;12918;12911:12;12864:61;12813:118;:::o;12937:135::-;12981:5;13019:6;13006:20;12997:29;;13035:31;13060:5;13035:31;:::i;:::-;12937:135;;;;:::o;13078:122::-;13151:24;13169:5;13151:24;:::i;:::-;13144:5;13141:35;13131:63;;13190:1;13187;13180:12;13131:63;13078:122;:::o;13206:139::-;13252:5;13290:6;13277:20;13268:29;;13306:33;13333:5;13306:33;:::i;:::-;13206:139;;;;:::o;13351:1053::-;13453:6;13461;13469;13477;13485;13493;13542:3;13530:9;13521:7;13517:23;13513:33;13510:120;;;13549:79;;:::i;:::-;13510:120;13669:1;13694:53;13739:7;13730:6;13719:9;13715:22;13694:53;:::i;:::-;13684:63;;13640:117;13796:2;13822:53;13867:7;13858:6;13847:9;13843:22;13822:53;:::i;:::-;13812:63;;13767:118;13924:2;13950:53;13995:7;13986:6;13975:9;13971:22;13950:53;:::i;:::-;13940:63;;13895:118;14052:2;14078:51;14121:7;14112:6;14101:9;14097:22;14078:51;:::i;:::-;14068:61;;14023:116;14178:3;14205:53;14250:7;14241:6;14230:9;14226:22;14205:53;:::i;:::-;14195:63;;14149:119;14307:3;14334:53;14379:7;14370:6;14359:9;14355:22;14334:53;:::i;:::-;14324:63;;14278:119;13351:1053;;;;;;;;:::o;14410:1199::-;14521:6;14529;14537;14545;14553;14561;14569;14618:3;14606:9;14597:7;14593:23;14589:33;14586:120;;;14625:79;;:::i;:::-;14586:120;14745:1;14770:53;14815:7;14806:6;14795:9;14791:22;14770:53;:::i;:::-;14760:63;;14716:117;14872:2;14898:53;14943:7;14934:6;14923:9;14919:22;14898:53;:::i;:::-;14888:63;;14843:118;15000:2;15026:53;15071:7;15062:6;15051:9;15047:22;15026:53;:::i;:::-;15016:63;;14971:118;15128:2;15154:53;15199:7;15190:6;15179:9;15175:22;15154:53;:::i;:::-;15144:63;;15099:118;15256:3;15283:51;15326:7;15317:6;15306:9;15302:22;15283:51;:::i;:::-;15273:61;;15227:117;15383:3;15410:53;15455:7;15446:6;15435:9;15431:22;15410:53;:::i;:::-;15400:63;;15354:119;15512:3;15539:53;15584:7;15575:6;15564:9;15560:22;15539:53;:::i;:::-;15529:63;;15483:119;14410:1199;;;;;;;;;;:::o;15615:474::-;15683:6;15691;15740:2;15728:9;15719:7;15715:23;15711:32;15708:119;;;15746:79;;:::i;:::-;15708:119;15866:1;15891:53;15936:7;15927:6;15916:9;15912:22;15891:53;:::i;:::-;15881:63;;15837:117;15993:2;16019:53;16064:7;16055:6;16044:9;16040:22;16019:53;:::i;:::-;16009:63;;15964:118;15615:474;;;;;:::o;16095:120::-;16167:23;16184:5;16167:23;:::i;:::-;16160:5;16157:34;16147:62;;16205:1;16202;16195:12;16147:62;16095:120;:::o;16221:137::-;16266:5;16304:6;16291:20;16282:29;;16320:32;16346:5;16320:32;:::i;:::-;16221:137;;;;:::o;16364:472::-;16431:6;16439;16488:2;16476:9;16467:7;16463:23;16459:32;16456:119;;;16494:79;;:::i;:::-;16456:119;16614:1;16639:53;16684:7;16675:6;16664:9;16660:22;16639:53;:::i;:::-;16629:63;;16585:117;16741:2;16767:52;16811:7;16802:6;16791:9;16787:22;16767:52;:::i;:::-;16757:62;;16712:117;16364:472;;;;;:::o;16842:105::-;16917:23;16934:5;16917:23;:::i;:::-;16912:3;16905:36;16842:105;;:::o;16953:142::-;16990:7;17030:58;17023:5;17019:70;17008:81;;16953:142;;;:::o;17101:108::-;17178:24;17196:5;17178:24;:::i;:::-;17173:3;17166:37;17101:108;;:::o;17283:517::-;17436:4;17431:3;17427:14;17528:4;17521:5;17517:16;17511:23;17547:61;17602:4;17597:3;17593:14;17579:12;17547:61;:::i;:::-;17451:167;17701:4;17694:5;17690:16;17684:23;17720:63;17777:4;17772:3;17768:14;17754:12;17720:63;:::i;:::-;17628:165;17405:395;17283:517;;:::o;17806:334::-;17955:4;17993:2;17982:9;17978:18;17970:26;;18006:127;18130:1;18119:9;18115:17;18106:6;18006:127;:::i;:::-;17806:334;;;;:::o;18146:180::-;18194:77;18191:1;18184:88;18291:4;18288:1;18281:15;18315:4;18312:1;18305:15;18332:320;18376:6;18413:1;18407:4;18403:12;18393:22;;18460:1;18454:4;18450:12;18481:18;18471:81;;18537:4;18529:6;18525:17;18515:27;;18471:81;18599:2;18591:6;18588:14;18568:18;18565:38;18562:84;;18618:18;;:::i;:::-;18562:84;18383:269;18332:320;;;:::o;18658:180::-;18706:77;18703:1;18696:88;18803:4;18800:1;18793:15;18827:4;18824:1;18817:15;18844:191;18884:3;18903:20;18921:1;18903:20;:::i;:::-;18898:25;;18937:20;18955:1;18937:20;:::i;:::-;18932:25;;18980:1;18977;18973:9;18966:16;;19001:3;18998:1;18995:10;18992:36;;;19008:18;;:::i;:::-;18992:36;18844:191;;;;:::o;19041:175::-;19181:27;19177:1;19169:6;19165:14;19158:51;19041:175;:::o;19222:366::-;19364:3;19385:67;19449:2;19444:3;19385:67;:::i;:::-;19378:74;;19461:93;19550:3;19461:93;:::i;:::-;19579:2;19574:3;19570:12;19563:19;;19222:366;;;:::o;19594:419::-;19760:4;19798:2;19787:9;19783:18;19775:26;;19847:9;19841:4;19837:20;19833:1;19822:9;19818:17;19811:47;19875:131;20001:4;19875:131;:::i;:::-;19867:139;;19594:419;;;:::o;20019:179::-;20159:31;20155:1;20147:6;20143:14;20136:55;20019:179;:::o;20204:366::-;20346:3;20367:67;20431:2;20426:3;20367:67;:::i;:::-;20360:74;;20443:93;20532:3;20443:93;:::i;:::-;20561:2;20556:3;20552:12;20545:19;;20204:366;;;:::o;20576:419::-;20742:4;20780:2;20769:9;20765:18;20757:26;;20829:9;20823:4;20819:20;20815:1;20804:9;20800:17;20793:47;20857:131;20983:4;20857:131;:::i;:::-;20849:139;;20576:419;;;:::o;21001:230::-;21141:34;21137:1;21129:6;21125:14;21118:58;21210:13;21205:2;21197:6;21193:15;21186:38;21001:230;:::o;21237:366::-;21379:3;21400:67;21464:2;21459:3;21400:67;:::i;:::-;21393:74;;21476:93;21565:3;21476:93;:::i;:::-;21594:2;21589:3;21585:12;21578:19;;21237:366;;;:::o;21609:419::-;21775:4;21813:2;21802:9;21798:18;21790:26;;21862:9;21856:4;21852:20;21848:1;21837:9;21833:17;21826:47;21890:131;22016:4;21890:131;:::i;:::-;21882:139;;21609:419;;;:::o;22034:168::-;22117:11;22151:6;22146:3;22139:19;22191:4;22186:3;22182:14;22167:29;;22034:168;;;;:::o;22208:146::-;22305:6;22300:3;22295;22282:30;22346:1;22337:6;22332:3;22328:16;22321:27;22208:146;;;:::o;22382:314::-;22478:3;22499:70;22562:6;22557:3;22499:70;:::i;:::-;22492:77;;22579:56;22628:6;22623:3;22616:5;22579:56;:::i;:::-;22660:29;22682:6;22660:29;:::i;:::-;22655:3;22651:39;22644:46;;22382:314;;;;;:::o;22702:771::-;22935:4;22973:3;22962:9;22958:19;22950:27;;22987:71;23055:1;23044:9;23040:17;23031:6;22987:71;:::i;:::-;23068:72;23136:2;23125:9;23121:18;23112:6;23068:72;:::i;:::-;23150;23218:2;23207:9;23203:18;23194:6;23150:72;:::i;:::-;23232;23300:2;23289:9;23285:18;23276:6;23232:72;:::i;:::-;23352:9;23346:4;23342:20;23336:3;23325:9;23321:19;23314:49;23380:86;23461:4;23452:6;23444;23380:86;:::i;:::-;23372:94;;22702:771;;;;;;;;;:::o;23479:143::-;23536:5;23567:6;23561:13;23552:22;;23583:33;23610:5;23583:33;:::i;:::-;23479:143;;;;:::o;23628:351::-;23698:6;23747:2;23735:9;23726:7;23722:23;23718:32;23715:119;;;23753:79;;:::i;:::-;23715:119;23873:1;23898:64;23954:7;23945:6;23934:9;23930:22;23898:64;:::i;:::-;23888:74;;23844:128;23628:351;;;;:::o;23985:223::-;24125:34;24121:1;24113:6;24109:14;24102:58;24194:6;24189:2;24181:6;24177:15;24170:31;23985:223;:::o;24214:366::-;24356:3;24377:67;24441:2;24436:3;24377:67;:::i;:::-;24370:74;;24453:93;24542:3;24453:93;:::i;:::-;24571:2;24566:3;24562:12;24555:19;;24214:366;;;:::o;24586:419::-;24752:4;24790:2;24779:9;24775:18;24767:26;;24839:9;24833:4;24829:20;24825:1;24814:9;24810:17;24803:47;24867:131;24993:4;24867:131;:::i;:::-;24859:139;;24586:419;;;:::o;25011:194::-;25051:4;25071:20;25089:1;25071:20;:::i;:::-;25066:25;;25105:20;25123:1;25105:20;:::i;:::-;25100:25;;25149:1;25146;25142:9;25134:17;;25173:1;25167:4;25164:11;25161:37;;;25178:18;;:::i;:::-;25161:37;25011:194;;;;:::o;25211:180::-;25259:77;25256:1;25249:88;25356:4;25353:1;25346:15;25380:4;25377:1;25370:15;25397:180;25445:77;25442:1;25435:88;25542:4;25539:1;25532:15;25566:4;25563:1;25556:15;25583:224;25723:34;25719:1;25711:6;25707:14;25700:58;25792:7;25787:2;25779:6;25775:15;25768:32;25583:224;:::o;25813:366::-;25955:3;25976:67;26040:2;26035:3;25976:67;:::i;:::-;25969:74;;26052:93;26141:3;26052:93;:::i;:::-;26170:2;26165:3;26161:12;26154:19;;25813:366;;;:::o;26185:419::-;26351:4;26389:2;26378:9;26374:18;26366:26;;26438:9;26432:4;26428:20;26424:1;26413:9;26409:17;26402:47;26466:131;26592:4;26466:131;:::i;:::-;26458:139;;26185:419;;;:::o;26610:179::-;26750:31;26746:1;26738:6;26734:14;26727:55;26610:179;:::o;26795:366::-;26937:3;26958:67;27022:2;27017:3;26958:67;:::i;:::-;26951:74;;27034:93;27123:3;27034:93;:::i;:::-;27152:2;27147:3;27143:12;27136:19;;26795:366;;;:::o;27167:419::-;27333:4;27371:2;27360:9;27356:18;27348:26;;27420:9;27414:4;27410:20;27406:1;27395:9;27391:17;27384:47;27448:131;27574:4;27448:131;:::i;:::-;27440:139;;27167:419;;;:::o;27592:553::-;27769:4;27807:3;27796:9;27792:19;27784:27;;27821:71;27889:1;27878:9;27874:17;27865:6;27821:71;:::i;:::-;27902:72;27970:2;27959:9;27955:18;27946:6;27902:72;:::i;:::-;27984;28052:2;28041:9;28037:18;28028:6;27984:72;:::i;:::-;28066;28134:2;28123:9;28119:18;28110:6;28066:72;:::i;:::-;27592:553;;;;;;;:::o;28151:175::-;28291:27;28287:1;28279:6;28275:14;28268:51;28151:175;:::o;28332:366::-;28474:3;28495:67;28559:2;28554:3;28495:67;:::i;:::-;28488:74;;28571:93;28660:3;28571:93;:::i;:::-;28689:2;28684:3;28680:12;28673:19;;28332:366;;;:::o;28704:419::-;28870:4;28908:2;28897:9;28893:18;28885:26;;28957:9;28951:4;28947:20;28943:1;28932:9;28928:17;28921:47;28985:131;29111:4;28985:131;:::i;:::-;28977:139;;28704:419;;;:::o;29129:179::-;29269:31;29265:1;29257:6;29253:14;29246:55;29129:179;:::o;29314:366::-;29456:3;29477:67;29541:2;29536:3;29477:67;:::i;:::-;29470:74;;29553:93;29642:3;29553:93;:::i;:::-;29671:2;29666:3;29662:12;29655:19;;29314:366;;;:::o;29686:419::-;29852:4;29890:2;29879:9;29875:18;29867:26;;29939:9;29933:4;29929:20;29925:1;29914:9;29910:17;29903:47;29967:131;30093:4;29967:131;:::i;:::-;29959:139;;29686:419;;;:::o;30111:775::-;30344:4;30382:3;30371:9;30367:19;30359:27;;30396:71;30464:1;30453:9;30449:17;30440:6;30396:71;:::i;:::-;30477:72;30545:2;30534:9;30530:18;30521:6;30477:72;:::i;:::-;30559;30627:2;30616:9;30612:18;30603:6;30559:72;:::i;:::-;30641;30709:2;30698:9;30694:18;30685:6;30641:72;:::i;:::-;30723:73;30791:3;30780:9;30776:19;30767:6;30723:73;:::i;:::-;30806;30874:3;30863:9;30859:19;30850:6;30806:73;:::i;:::-;30111:775;;;;;;;;;:::o;30892:180::-;31032:32;31028:1;31020:6;31016:14;31009:56;30892:180;:::o;31078:366::-;31220:3;31241:67;31305:2;31300:3;31241:67;:::i;:::-;31234:74;;31317:93;31406:3;31317:93;:::i;:::-;31435:2;31430:3;31426:12;31419:19;;31078:366;;;:::o;31450:419::-;31616:4;31654:2;31643:9;31639:18;31631:26;;31703:9;31697:4;31693:20;31689:1;31678:9;31674:17;31667:47;31731:131;31857:4;31731:131;:::i;:::-;31723:139;;31450:419;;;:::o;31875:177::-;32015:29;32011:1;32003:6;31999:14;31992:53;31875:177;:::o;32058:366::-;32200:3;32221:67;32285:2;32280:3;32221:67;:::i;:::-;32214:74;;32297:93;32386:3;32297:93;:::i;:::-;32415:2;32410:3;32406:12;32399:19;;32058:366;;;:::o;32430:419::-;32596:4;32634:2;32623:9;32619:18;32611:26;;32683:9;32677:4;32673:20;32669:1;32658:9;32654:17;32647:47;32711:131;32837:4;32711:131;:::i;:::-;32703:139;;32430:419;;;:::o;32855:225::-;32995:34;32991:1;32983:6;32979:14;32972:58;33064:8;33059:2;33051:6;33047:15;33040:33;32855:225;:::o;33086:366::-;33228:3;33249:67;33313:2;33308:3;33249:67;:::i;:::-;33242:74;;33325:93;33414:3;33325:93;:::i;:::-;33443:2;33438:3;33434:12;33427:19;;33086:366;;;:::o;33458:419::-;33624:4;33662:2;33651:9;33647:18;33639:26;;33711:9;33705:4;33701:20;33697:1;33686:9;33682:17;33675:47;33739:131;33865:4;33739:131;:::i;:::-;33731:139;;33458:419;;;:::o;33883:141::-;33932:4;33955:3;33947:11;;33978:3;33975:1;33968:14;34012:4;34009:1;33999:18;33991:26;;33883:141;;;:::o;34030:93::-;34067:6;34114:2;34109;34102:5;34098:14;34094:23;34084:33;;34030:93;;;:::o;34129:107::-;34173:8;34223:5;34217:4;34213:16;34192:37;;34129:107;;;;:::o;34242:393::-;34311:6;34361:1;34349:10;34345:18;34384:97;34414:66;34403:9;34384:97;:::i;:::-;34502:39;34532:8;34521:9;34502:39;:::i;:::-;34490:51;;34574:4;34570:9;34563:5;34559:21;34550:30;;34623:4;34613:8;34609:19;34602:5;34599:30;34589:40;;34318:317;;34242:393;;;;;:::o;34641:60::-;34669:3;34690:5;34683:12;;34641:60;;;:::o;34707:142::-;34757:9;34790:53;34808:34;34817:24;34835:5;34817:24;:::i;:::-;34808:34;:::i;:::-;34790:53;:::i;:::-;34777:66;;34707:142;;;:::o;34855:75::-;34898:3;34919:5;34912:12;;34855:75;;;:::o;34936:269::-;35046:39;35077:7;35046:39;:::i;:::-;35107:91;35156:41;35180:16;35156:41;:::i;:::-;35148:6;35141:4;35135:11;35107:91;:::i;:::-;35101:4;35094:105;35012:193;34936:269;;;:::o;35211:73::-;35256:3;35211:73;:::o;35290:189::-;35367:32;;:::i;:::-;35408:65;35466:6;35458;35452:4;35408:65;:::i;:::-;35343:136;35290:189;;:::o;35485:186::-;35545:120;35562:3;35555:5;35552:14;35545:120;;;35616:39;35653:1;35646:5;35616:39;:::i;:::-;35589:1;35582:5;35578:13;35569:22;;35545:120;;;35485:186;;:::o;35677:543::-;35778:2;35773:3;35770:11;35767:446;;;35812:38;35844:5;35812:38;:::i;:::-;35896:29;35914:10;35896:29;:::i;:::-;35886:8;35882:44;36079:2;36067:10;36064:18;36061:49;;;36100:8;36085:23;;36061:49;36123:80;36179:22;36197:3;36179:22;:::i;:::-;36169:8;36165:37;36152:11;36123:80;:::i;:::-;35782:431;;35767:446;35677:543;;;:::o;36226:117::-;36280:8;36330:5;36324:4;36320:16;36299:37;;36226:117;;;;:::o;36349:169::-;36393:6;36426:51;36474:1;36470:6;36462:5;36459:1;36455:13;36426:51;:::i;:::-;36422:56;36507:4;36501;36497:15;36487:25;;36400:118;36349:169;;;;:::o;36523:295::-;36599:4;36745:29;36770:3;36764:4;36745:29;:::i;:::-;36737:37;;36807:3;36804:1;36800:11;36794:4;36791:21;36783:29;;36523:295;;;;:::o;36823:1395::-;36940:37;36973:3;36940:37;:::i;:::-;37042:18;37034:6;37031:30;37028:56;;;37064:18;;:::i;:::-;37028:56;37108:38;37140:4;37134:11;37108:38;:::i;:::-;37193:67;37253:6;37245;37239:4;37193:67;:::i;:::-;37287:1;37311:4;37298:17;;37343:2;37335:6;37332:14;37360:1;37355:618;;;;38017:1;38034:6;38031:77;;;38083:9;38078:3;38074:19;38068:26;38059:35;;38031:77;38134:67;38194:6;38187:5;38134:67;:::i;:::-;38128:4;38121:81;37990:222;37325:887;;37355:618;37407:4;37403:9;37395:6;37391:22;37441:37;37473:4;37441:37;:::i;:::-;37500:1;37514:208;37528:7;37525:1;37522:14;37514:208;;;37607:9;37602:3;37598:19;37592:26;37584:6;37577:42;37658:1;37650:6;37646:14;37636:24;;37705:2;37694:9;37690:18;37677:31;;37551:4;37548:1;37544:12;37539:17;;37514:208;;;37750:6;37741:7;37738:19;37735:179;;;37808:9;37803:3;37799:19;37793:26;37851:48;37893:4;37885:6;37881:17;37870:9;37851:48;:::i;:::-;37843:6;37836:64;37758:156;37735:179;37960:1;37956;37948:6;37944:14;37940:22;37934:4;37927:36;37362:611;;;37325:887;;36915:1303;;;36823:1395;;:::o;38224:235::-;38364:34;38360:1;38352:6;38348:14;38341:58;38433:18;38428:2;38420:6;38416:15;38409:43;38224:235;:::o;38465:366::-;38607:3;38628:67;38692:2;38687:3;38628:67;:::i;:::-;38621:74;;38704:93;38793:3;38704:93;:::i;:::-;38822:2;38817:3;38813:12;38806:19;;38465:366;;;:::o;38837:419::-;39003:4;39041:2;39030:9;39026:18;39018:26;;39090:9;39084:4;39080:20;39076:1;39065:9;39061:17;39054:47;39118:131;39244:4;39118:131;:::i;:::-;39110:139;;38837:419;;;:::o;39262:181::-;39402:33;39398:1;39390:6;39386:14;39379:57;39262:181;:::o;39449:366::-;39591:3;39612:67;39676:2;39671:3;39612:67;:::i;:::-;39605:74;;39688:93;39777:3;39688:93;:::i;:::-;39806:2;39801:3;39797:12;39790:19;;39449:366;;;:::o;39821:419::-;39987:4;40025:2;40014:9;40010:18;40002:26;;40074:9;40068:4;40064:20;40060:1;40049:9;40045:17;40038:47;40102:131;40228:4;40102:131;:::i;:::-;40094:139;;39821:419;;;:::o;40246:226::-;40386:34;40382:1;40374:6;40370:14;40363:58;40455:9;40450:2;40442:6;40438:15;40431:34;40246:226;:::o;40478:366::-;40620:3;40641:67;40705:2;40700:3;40641:67;:::i;:::-;40634:74;;40717:93;40806:3;40717:93;:::i;:::-;40835:2;40830:3;40826:12;40819:19;;40478:366;;;:::o;40850:419::-;41016:4;41054:2;41043:9;41039:18;41031:26;;41103:9;41097:4;41093:20;41089:1;41078:9;41074:17;41067:47;41131:131;41257:4;41131:131;:::i;:::-;41123:139;;40850:419;;;:::o;41275:225::-;41415:34;41411:1;41403:6;41399:14;41392:58;41484:8;41479:2;41471:6;41467:15;41460:33;41275:225;:::o;41506:366::-;41648:3;41669:67;41733:2;41728:3;41669:67;:::i;:::-;41662:74;;41745:93;41834:3;41745:93;:::i;:::-;41863:2;41858:3;41854:12;41847:19;;41506:366;;;:::o;41878:419::-;42044:4;42082:2;42071:9;42067:18;42059:26;;42131:9;42125:4;42121:20;42117:1;42106:9;42102:17;42095:47;42159:131;42285:4;42159:131;:::i;:::-;42151:139;;41878:419;;;:::o;42303:225::-;42443:34;42439:1;42431:6;42427:14;42420:58;42512:8;42507:2;42499:6;42495:15;42488:33;42303:225;:::o;42534:366::-;42676:3;42697:67;42761:2;42756:3;42697:67;:::i;:::-;42690:74;;42773:93;42862:3;42773:93;:::i;:::-;42891:2;42886:3;42882:12;42875:19;;42534:366;;;:::o;42906:419::-;43072:4;43110:2;43099:9;43095:18;43087:26;;43159:9;43153:4;43149:20;43145:1;43134:9;43130:17;43123:47;43187:131;43313:4;43187:131;:::i;:::-;43179:139;;42906:419;;;:::o;43331:223::-;43471:34;43467:1;43459:6;43455:14;43448:58;43540:6;43535:2;43527:6;43523:15;43516:31;43331:223;:::o;43560:366::-;43702:3;43723:67;43787:2;43782:3;43723:67;:::i;:::-;43716:74;;43799:93;43888:3;43799:93;:::i;:::-;43917:2;43912:3;43908:12;43901:19;;43560:366;;;:::o;43932:419::-;44098:4;44136:2;44125:9;44121:18;44113:26;;44185:9;44179:4;44175:20;44171:1;44160:9;44156:17;44149:47;44213:131;44339:4;44213:131;:::i;:::-;44205:139;;43932:419;;;:::o;44357:221::-;44497:34;44493:1;44485:6;44481:14;44474:58;44566:4;44561:2;44553:6;44549:15;44542:29;44357:221;:::o;44584:366::-;44726:3;44747:67;44811:2;44806:3;44747:67;:::i;:::-;44740:74;;44823:93;44912:3;44823:93;:::i;:::-;44941:2;44936:3;44932:12;44925:19;;44584:366;;;:::o;44956:419::-;45122:4;45160:2;45149:9;45145:18;45137:26;;45209:9;45203:4;45199:20;45195:1;45184:9;45180:17;45173:47;45237:131;45363:4;45237:131;:::i;:::-;45229:139;;44956:419;;;:::o;45381:179::-;45521:31;45517:1;45509:6;45505:14;45498:55;45381:179;:::o;45566:366::-;45708:3;45729:67;45793:2;45788:3;45729:67;:::i;:::-;45722:74;;45805:93;45894:3;45805:93;:::i;:::-;45923:2;45918:3;45914:12;45907:19;;45566:366;;;:::o;45938:419::-;46104:4;46142:2;46131:9;46127:18;46119:26;;46191:9;46185:4;46181:20;46177:1;46166:9;46162:17;46155:47;46219:131;46345:4;46219:131;:::i;:::-;46211:139;;45938:419;;;:::o;46363:224::-;46503:34;46499:1;46491:6;46487:14;46480:58;46572:7;46567:2;46559:6;46555:15;46548:32;46363:224;:::o;46593:366::-;46735:3;46756:67;46820:2;46815:3;46756:67;:::i;:::-;46749:74;;46832:93;46921:3;46832:93;:::i;:::-;46950:2;46945:3;46941:12;46934:19;;46593:366;;;:::o;46965:419::-;47131:4;47169:2;47158:9;47154:18;47146:26;;47218:9;47212:4;47208:20;47204:1;47193:9;47189:17;47182:47;47246:131;47372:4;47246:131;:::i;:::-;47238:139;;46965:419;;;:::o;47390:222::-;47530:34;47526:1;47518:6;47514:14;47507:58;47599:5;47594:2;47586:6;47582:15;47575:30;47390:222;:::o;47618:366::-;47760:3;47781:67;47845:2;47840:3;47781:67;:::i;:::-;47774:74;;47857:93;47946:3;47857:93;:::i;:::-;47975:2;47970:3;47966:12;47959:19;;47618:366;;;:::o;47990:419::-;48156:4;48194:2;48183:9;48179:18;48171:26;;48243:9;48237:4;48233:20;48229:1;48218:9;48214:17;48207:47;48271:131;48397:4;48271:131;:::i;:::-;48263:139;;47990:419;;;:::o;48415:225::-;48555:34;48551:1;48543:6;48539:14;48532:58;48624:8;48619:2;48611:6;48607:15;48600:33;48415:225;:::o;48646:366::-;48788:3;48809:67;48873:2;48868:3;48809:67;:::i;:::-;48802:74;;48885:93;48974:3;48885:93;:::i;:::-;49003:2;48998:3;48994:12;48987:19;;48646:366;;;:::o;49018:419::-;49184:4;49222:2;49211:9;49207:18;49199:26;;49271:9;49265:4;49261:20;49257:1;49246:9;49242:17;49235:47;49299:131;49425:4;49299:131;:::i;:::-;49291:139;;49018:419;;;:::o;49443:182::-;49583:34;49579:1;49571:6;49567:14;49560:58;49443:182;:::o;49631:366::-;49773:3;49794:67;49858:2;49853:3;49794:67;:::i;:::-;49787:74;;49870:93;49959:3;49870:93;:::i;:::-;49988:2;49983:3;49979:12;49972:19;;49631:366;;;:::o;50003:419::-;50169:4;50207:2;50196:9;50192:18;50184:26;;50256:9;50250:4;50246:20;50242:1;50231:9;50227:17;50220:47;50284:131;50410:4;50284:131;:::i;:::-;50276:139;;50003:419;;;:::o;50428:172::-;50568:24;50564:1;50556:6;50552:14;50545:48;50428:172;:::o;50606:366::-;50748:3;50769:67;50833:2;50828:3;50769:67;:::i;:::-;50762:74;;50845:93;50934:3;50845:93;:::i;:::-;50963:2;50958:3;50954:12;50947:19;;50606:366;;;:::o;50978:419::-;51144:4;51182:2;51171:9;51167:18;51159:26;;51231:9;51225:4;51221:20;51217:1;51206:9;51202:17;51195:47;51259:131;51385:4;51259:131;:::i;:::-;51251:139;;50978:419;;;:::o;51403:179::-;51543:31;51539:1;51531:6;51527:14;51520:55;51403:179;:::o;51588:366::-;51730:3;51751:67;51815:2;51810:3;51751:67;:::i;:::-;51744:74;;51827:93;51916:3;51827:93;:::i;:::-;51945:2;51940:3;51936:12;51929:19;;51588:366;;;:::o;51960:419::-;52126:4;52164:2;52153:9;52149:18;52141:26;;52213:9;52207:4;52203:20;52199:1;52188:9;52184:17;52177:47;52241:131;52367:4;52241:131;:::i;:::-;52233:139;;51960:419;;;:::o;52385:98::-;52436:6;52470:5;52464:12;52454:22;;52385:98;;;:::o;52489:116::-;52540:4;52563:3;52555:11;;52593:4;52588:3;52584:14;52576:22;;52489:116;;;:::o;52611:154::-;52654:11;52690:29;52714:3;52708:10;52690:29;:::i;:::-;52753:5;52729:29;;52666:99;52611:154;;;:::o;52771:594::-;52855:5;52886:38;52918:5;52886:38;:::i;:::-;52949:5;52976:40;53010:5;52976:40;:::i;:::-;52964:52;;53035:35;53061:8;53035:35;:::i;:::-;53026:44;;53094:2;53086:6;53083:14;53080:278;;;53165:169;53250:66;53220:6;53216:2;53212:15;53209:1;53205:23;53165:169;:::i;:::-;53142:5;53121:227;53112:236;;53080:278;52861:504;;52771:594;;;:::o;53371:332::-;53492:4;53530:2;53519:9;53515:18;53507:26;;53543:71;53611:1;53600:9;53596:17;53587:6;53543:71;:::i;:::-;53624:72;53692:2;53681:9;53677:18;53668:6;53624:72;:::i;:::-;53371:332;;;;;:::o;53709:664::-;53914:4;53952:3;53941:9;53937:19;53929:27;;53966:71;54034:1;54023:9;54019:17;54010:6;53966:71;:::i;:::-;54047:72;54115:2;54104:9;54100:18;54091:6;54047:72;:::i;:::-;54129;54197:2;54186:9;54182:18;54173:6;54129:72;:::i;:::-;54211;54279:2;54268:9;54264:18;54255:6;54211:72;:::i;:::-;54293:73;54361:3;54350:9;54346:19;54337:6;54293:73;:::i;:::-;53709:664;;;;;;;;:::o;54379:180::-;54427:77;54424:1;54417:88;54524:4;54521:1;54514:15;54548:4;54545:1;54538:15;54565:185;54605:1;54622:20;54640:1;54622:20;:::i;:::-;54617:25;;54656:20;54674:1;54656:20;:::i;:::-;54651:25;;54695:1;54685:35;;54700:18;;:::i;:::-;54685:35;54742:1;54739;54735:9;54730:14;;54565:185;;;;:::o;54756:170::-;54896:22;54892:1;54884:6;54880:14;54873:46;54756:170;:::o;54932:366::-;55074:3;55095:67;55159:2;55154:3;55095:67;:::i;:::-;55088:74;;55171:93;55260:3;55171:93;:::i;:::-;55289:2;55284:3;55280:12;55273:19;;54932:366;;;:::o;55304:419::-;55470:4;55508:2;55497:9;55493:18;55485:26;;55557:9;55551:4;55547:20;55543:1;55532:9;55528:17;55521:47;55585:131;55711:4;55585:131;:::i;:::-;55577:139;;55304:419;;;:::o;55729:166::-;55869:18;55865:1;55857:6;55853:14;55846:42;55729:166;:::o;55901:366::-;56043:3;56064:67;56128:2;56123:3;56064:67;:::i;:::-;56057:74;;56140:93;56229:3;56140:93;:::i;:::-;56258:2;56253:3;56249:12;56242:19;;55901:366;;;:::o;56273:419::-;56439:4;56477:2;56466:9;56462:18;56454:26;;56526:9;56520:4;56516:20;56512:1;56501:9;56497:17;56490:47;56554:131;56680:4;56554:131;:::i;:::-;56546:139;;56273:419;;;:::o;56698:545::-;56871:4;56909:3;56898:9;56894:19;56886:27;;56923:71;56991:1;56980:9;56976:17;56967:6;56923:71;:::i;:::-;57004:68;57068:2;57057:9;57053:18;57044:6;57004:68;:::i;:::-;57082:72;57150:2;57139:9;57135:18;57126:6;57082:72;:::i;:::-;57164;57232:2;57221:9;57217:18;57208:6;57164:72;:::i;:::-;56698:545;;;;;;;:::o;57249:180::-;57297:77;57294:1;57287:88;57394:4;57391:1;57384:15;57418:4;57415:1;57408:15;57435:174;57575:26;57571:1;57563:6;57559:14;57552:50;57435:174;:::o;57615:366::-;57757:3;57778:67;57842:2;57837:3;57778:67;:::i;:::-;57771:74;;57854:93;57943:3;57854:93;:::i;:::-;57972:2;57967:3;57963:12;57956:19;;57615:366;;;:::o;57987:419::-;58153:4;58191:2;58180:9;58176:18;58168:26;;58240:9;58234:4;58230:20;58226:1;58215:9;58211:17;58204:47;58268:131;58394:4;58268:131;:::i;:::-;58260:139;;57987:419;;;:::o;58412:181::-;58552:33;58548:1;58540:6;58536:14;58529:57;58412:181;:::o;58599:366::-;58741:3;58762:67;58826:2;58821:3;58762:67;:::i;:::-;58755:74;;58838:93;58927:3;58838:93;:::i;:::-;58956:2;58951:3;58947:12;58940:19;;58599:366;;;:::o;58971:419::-;59137:4;59175:2;59164:9;59160:18;59152:26;;59224:9;59218:4;59214:20;59210:1;59199:9;59195:17;59188:47;59252:131;59378:4;59252:131;:::i;:::-;59244:139;;58971:419;;;:::o;59396:221::-;59536:34;59532:1;59524:6;59520:14;59513:58;59605:4;59600:2;59592:6;59588:15;59581:29;59396:221;:::o;59623:366::-;59765:3;59786:67;59850:2;59845:3;59786:67;:::i;:::-;59779:74;;59862:93;59951:3;59862:93;:::i;:::-;59980:2;59975:3;59971:12;59964:19;;59623:366;;;:::o;59995:419::-;60161:4;60199:2;60188:9;60184:18;60176:26;;60248:9;60242:4;60238:20;60234:1;60223:9;60219:17;60212:47;60276:131;60402:4;60276:131;:::i;:::-;60268:139;;59995:419;;;:::o;60420:220::-;60560:34;60556:1;60548:6;60544:14;60537:58;60629:3;60624:2;60616:6;60612:15;60605:28;60420:220;:::o;60646:366::-;60788:3;60809:67;60873:2;60868:3;60809:67;:::i;:::-;60802:74;;60885:93;60974:3;60885:93;:::i;:::-;61003:2;60998:3;60994:12;60987:19;;60646:366;;;:::o;61018:419::-;61184:4;61222:2;61211:9;61207:18;61199:26;;61271:9;61265:4;61261:20;61257:1;61246:9;61242:17;61235:47;61299:131;61425:4;61299:131;:::i;:::-;61291:139;;61018:419;;;:::o;61443:221::-;61583:34;61579:1;61571:6;61567:14;61560:58;61652:4;61647:2;61639:6;61635:15;61628:29;61443:221;:::o;61670:366::-;61812:3;61833:67;61897:2;61892:3;61833:67;:::i;:::-;61826:74;;61909:93;61998:3;61909:93;:::i;:::-;62027:2;62022:3;62018:12;62011:19;;61670:366;;;:::o;62042:419::-;62208:4;62246:2;62235:9;62231:18;62223:26;;62295:9;62289:4;62285:20;62281:1;62270:9;62266:17;62259:47;62323:131;62449:4;62323:131;:::i;:::-;62315:139;;62042:419;;;:::o

Swarm Source

ipfs://1e3a95ac0ea6e47958a92f595fe6c769b6cfaf49b623370daaaf649523da853e
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.