ETH Price: $2,458.40 (-8.26%)

Token

MAGE (MAGE)
 

Overview

Max Total Supply

88,888,888,888 MAGE

Holders

60

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
0.85289577047524234 MAGE

Value
$0.00
0x58b22465b7041b5f98f81f4ab2597abb0b1efa39
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:
MAGE

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-05-07
*/

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


// OpenZeppelin Contracts (last updated v4.7.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 "IERC3156FlashBorrower.onFlashLoan"
     */
    function onFlashLoan(
        address initiator,
        address token,
        uint256 amount,
        uint256 fee,
        bytes calldata data
    ) external returns (bytes32);
}

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


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

pragma solidity ^0.8.0;


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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


// OpenZeppelin Contracts (last updated v4.5.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 the end of a past block (`blockNumber`).
     */
    function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).
     *
     * 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 blockNumber) external view returns (uint256);

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

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

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

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


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

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

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

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

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


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

pragma solidity ^0.8.0;

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

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


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

pragma solidity ^0.8.0;


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

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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


// OpenZeppelin Contracts (last updated v4.8.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) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 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 10, 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 * 8) < value ? 1 : 0);
        }
    }
}

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


// OpenZeppelin Contracts (last updated v4.8.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 `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);
    }
}

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


// OpenZeppelin Contracts (last updated v4.8.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) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @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) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

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


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

pragma solidity ^0.8.0;


/**
 * @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].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // 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 _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;
    address private immutable _CACHED_THIS;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @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) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _CACHED_THIS = address(this);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, 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);
    }
}

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


// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)

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:
 * ```
 * 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`, and `uint256`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 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
        }
    }
}

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


// OpenZeppelin Contracts (last updated v4.8.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;
        /// @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;
        /// @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;
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getUint256Slot();
    }
}

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


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

pragma solidity ^0.8.0;

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

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

// File: @openzeppelin/[email protected]/security/Pausable.sol


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

pragma solidity ^0.8.0;


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

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

    bool private _paused;

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;





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

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

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

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

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

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

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

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

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

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

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

        _revokeRole(role, account);
    }

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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


// OpenZeppelin Contracts (last updated v4.8.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].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

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

        _beforeTokenTransfer(from, to, amount);

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

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;




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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;






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

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

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

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

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

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

        bytes32 hash = _hashTypedDataV4(structHash);

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

        _approve(owner, spender, value);
    }

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

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

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

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


// OpenZeppelin Contracts (last updated v4.8.1) (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 IVotes, ERC20Permit {
    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 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;
        return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
    }

    /**
     * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.
     *
     * Requirements:
     *
     * - `blockNumber` must have been already mined
     */
    function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
        require(blockNumber < block.number, "ERC20Votes: block not yet mined");
        return _checkpointsLookup(_checkpoints[account], blockNumber);
    }

    /**
     * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.
     * It is but NOT the sum of all the delegated votes!
     *
     * Requirements:
     *
     * - `blockNumber` must have been already mined
     */
    function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {
        require(blockNumber < block.number, "ERC20Votes: block not yet mined");
        return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
    }

    /**
     * @dev Lookup a value in a list of (sorted) checkpoints.
     */
    function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {
        // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.
        //
        // 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 `blockNumber`, we look in [low, mid)
        // - If the middle checkpoint is before or equal to `blockNumber`, 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 `blockNumber`, we end up with an index that is
        // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, 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 > blockNumber) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

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

        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;

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;




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

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

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

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

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

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

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

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

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

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

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

        return snapshotted ? value : balanceOf(account);
    }

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

        return snapshotted ? value : totalSupply();
    }

    // Update balance and/or total supply snapshots before the values are modified. This is implemented
    // in the _beforeTokenTransfer hook, which is executed for _mint, _burn, and _transfer operations.
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;



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

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

// File: contract-f540e939d1.sol


pragma solidity ^0.8.9;









contract MAGE is ERC20, ERC20Burnable, ERC20Snapshot, AccessControl, Pausable, ERC20Permit, ERC20Votes, ERC20FlashMint {
    bytes32 public constant SNAPSHOT_ROLE = keccak256("SNAPSHOT_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    constructor() ERC20("MAGE", "MAGE") ERC20Permit("MAGE") {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(SNAPSHOT_ROLE, msg.sender);
        _grantRole(PAUSER_ROLE, msg.sender);
        _mint(msg.sender, 88888888888 * 10 ** decimals());
        _grantRole(MINTER_ROLE, msg.sender);
    }

    function snapshot() public onlyRole(SNAPSHOT_ROLE) {
        _snapshot();
    }

    function pause() public onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() public onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
        _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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Snapshot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SNAPSHOT_ROLE","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":"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":[{"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":"blockNumber","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"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":"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":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"snapshot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101406040523480156200001257600080fd5b506040518060400160405280600481526020017f4d41474500000000000000000000000000000000000000000000000000000000815250806040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f4d414745000000000000000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f4d414745000000000000000000000000000000000000000000000000000000008152508160039081620000fd9190620013ef565b5080600490816200010f9190620013ef565b5050506000600a60006101000a81548160ff02191690831515021790555060008280519060200120905060008280519060200120905060007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90508260e081815250508161010081815250504660a0818152505062000196818484620002d260201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1681525050806101208181525050505050505050620001f56000801b336200030e60201b60201c565b620002277f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f336200030e60201b60201c565b620002597f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336200030e60201b60201c565b6200029a336200026e6200040060201b60201c565b600a6200027c919062001666565b6414b230ce386200028e9190620016b7565b6200040960201b60201c565b620002cc7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200030e60201b60201c565b62001b7c565b60008383834630604051602001620002ef95949392919062001773565b6040516020818303038152906040528051906020012090509392505050565b6200032082826200042460201b60201c565b620003fc5760016009600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620003a16200048f60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006012905090565b6200042082826200049760201b620019711760201c565b5050565b60006009600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600033905090565b620004ae82826200055560201b620019fe1760201c565b620004be620006c260201b60201c565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16620004ec620006e660201b60201c565b111562000530576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005279062001857565b60405180910390fd5b6200054f600f620006f060201b62001b5417836200070860201b60201c565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620005c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005be90620018c9565b60405180910390fd5b620005db6000838362000a1560201b60201c565b8060026000828254620005ef9190620018eb565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051620006a2919062001926565b60405180910390a3620006be6000838362000a4260201b60201c565b5050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b6000600254905090565b60008183620007009190620018eb565b905092915050565b6000806000858054905090506000808214620007e3576200073e8760018462000732919062001943565b62000a5f60201b60201c565b6040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815250506200081f565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152505b905080602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1693506200085284868860201c565b92506000821180156200086e575043816000015163ffffffff16145b1562000901576200088a8362000a7460201b62001b6a1760201c565b620008aa886001856200089e919062001943565b62000a5f60201b60201c565b60000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555062000a0b565b866040518060400160405280620009234362000ae260201b62001bd51760201c565b63ffffffff168152602001620009448662000a7460201b62001b6a1760201c565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555050505b5050935093915050565b62000a2562000b3860201b60201c565b62000a3d83838362000b8d60201b62001c281760201c565b505050565b62000a5a83838362000c8660201b62001ce01760201c565b505050565b60008260005281602060002001905092915050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff801682111562000ada576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000ad190620019f4565b60405180910390fd5b819050919050565b600063ffffffff801682111562000b30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000b279062001a8c565b60405180910390fd5b819050919050565b62000b4862000cd660201b60201c565b1562000b8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000b829062001afe565b60405180910390fd5b565b62000ba583838362000ced60201b62001d0b1760201c565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000c015762000beb8262000cf260201b60201c565b62000bfb62000d5560201b60201c565b62000c81565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000c5d5762000c478362000cf260201b60201c565b62000c5762000d5560201b60201c565b62000c80565b62000c6e8362000cf260201b60201c565b62000c7f8262000cf260201b60201c565b5b5b505050565b62000c9e83838362000d7960201b62001d101760201c565b62000cd162000cb38462000d7e60201b60201c565b62000cc48462000d7e60201b60201c565b8362000de760201b60201c565b505050565b6000600a60009054906101000a900460ff16905090565b505050565b62000d52600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002062000d46836200100a60201b60201c565b6200105260201b60201c565b50565b62000d77600662000d6b620006e660201b60201c565b6200105260201b60201c565b565b505050565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801562000e245750600081115b156200100557600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161462000f175760008062000ebe600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020620010de60201b62001d1517856200070860201b60201c565b915091508473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405162000f0c92919062001b20565b60405180910390a250505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614620010045760008062000fab600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020620006f060201b62001b5417856200070860201b60201c565b915091508373ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405162000ff992919062001b20565b60405180910390a250505b5b505050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600062001064620010f660201b60201c565b9050806200107b846000016200111460201b60201c565b1015620010d95782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b60008183620010ee919062001943565b905092915050565b60006200110f60086200116760201b62001d2b1760201c565b905090565b6000808280549050036200112c576000905062001162565b816001838054905062001140919062001943565b8154811062001154576200115362001b4d565b5b906000526020600020015490505b919050565b600081600001549050919050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620011f757607f821691505b6020821081036200120d576200120c620011af565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620012777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262001238565b62001283868362001238565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620012d0620012ca620012c4846200129b565b620012a5565b6200129b565b9050919050565b6000819050919050565b620012ec83620012af565b62001304620012fb82620012d7565b84845462001245565b825550505050565b600090565b6200131b6200130c565b62001328818484620012e1565b505050565b5b8181101562001350576200134460008262001311565b6001810190506200132e565b5050565b601f8211156200139f57620013698162001213565b620013748462001228565b8101602085101562001384578190505b6200139c620013938562001228565b8301826200132d565b50505b505050565b600082821c905092915050565b6000620013c460001984600802620013a4565b1980831691505092915050565b6000620013df8383620013b1565b9150826002028217905092915050565b620013fa8262001175565b67ffffffffffffffff81111562001416576200141562001180565b5b620014228254620011de565b6200142f82828562001354565b600060209050601f83116001811462001467576000841562001452578287015190505b6200145e8582620013d1565b865550620014ce565b601f198416620014778662001213565b60005b82811015620014a1578489015182556001820191506020850194506020810190506200147a565b86831015620014c15784890151620014bd601f891682620013b1565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b600185111562001564578086048111156200153c576200153b620014d6565b5b60018516156200154c5780820291505b80810290506200155c8562001505565b94506200151c565b94509492505050565b6000826200157f576001905062001652565b816200158f576000905062001652565b8160018114620015a85760028114620015b357620015e9565b600191505062001652565b60ff841115620015c857620015c7620014d6565b5b8360020a915084821115620015e257620015e1620014d6565b5b5062001652565b5060208310610133831016604e8410600b8410161715620016235782820a9050838111156200161d576200161c620014d6565b5b62001652565b62001632848484600162001512565b925090508184048111156200164c576200164b620014d6565b5b81810290505b9392505050565b600060ff82169050919050565b600062001673826200129b565b9150620016808362001659565b9250620016af7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846200156d565b905092915050565b6000620016c4826200129b565b9150620016d1836200129b565b9250828202620016e1816200129b565b91508282048414831517620016fb57620016fa620014d6565b5b5092915050565b6000819050919050565b620017178162001702565b82525050565b62001728816200129b565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200175b826200172e565b9050919050565b6200176d816200174e565b82525050565b600060a0820190506200178a60008301886200170c565b6200179960208301876200170c565b620017a860408301866200170c565b620017b760608301856200171d565b620017c6608083018462001762565b9695505050505050565b600082825260208201905092915050565b7f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60008201527f766572666c6f77696e6720766f74657300000000000000000000000000000000602082015250565b60006200183f603083620017d0565b91506200184c82620017e1565b604082019050919050565b60006020820190508181036000830152620018728162001830565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b6000620018b1601f83620017d0565b9150620018be8262001879565b602082019050919050565b60006020820190508181036000830152620018e481620018a2565b9050919050565b6000620018f8826200129b565b915062001905836200129b565b925082820190508082111562001920576200191f620014d6565b5b92915050565b60006020820190506200193d60008301846200171d565b92915050565b600062001950826200129b565b91506200195d836200129b565b9250828203905081811115620019785762001977620014d6565b5b92915050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203260008201527f3234206269747300000000000000000000000000000000000000000000000000602082015250565b6000620019dc602783620017d0565b9150620019e9826200197e565b604082019050919050565b6000602082019050818103600083015262001a0f81620019cd565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203360008201527f3220626974730000000000000000000000000000000000000000000000000000602082015250565b600062001a74602683620017d0565b915062001a818262001a16565b604082019050919050565b6000602082019050818103600083015262001aa78162001a65565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600062001ae6601083620017d0565b915062001af38262001aae565b602082019050919050565b6000602082019050818103600083015262001b198162001ad7565b9050919050565b600060408201905062001b3760008301856200171d565b62001b4660208301846200171d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60805160a05160c05160e0516101005161012051615a4162001bcc60003960006124190152600061245b0152600061243a0152600061236f015260006123c5015260006123ee0152615a416000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80637028e2cd11610151578063a217fddf116100c3578063d539139311610087578063d5391393146107f7578063d547741f14610815578063d9d98ce414610831578063dd62ed3e14610861578063e63ab1e914610891578063f1127ed8146108af57610274565b8063a217fddf14610741578063a457c2d71461075f578063a9059cbb1461078f578063c3cda520146107bf578063d505accf146107db57610274565b80638e539e8c116101155780638e539e8c1461065957806391d148541461068957806395d89b41146106b95780639711715a146106d7578063981b24d0146106e15780639ab24eb01461071157610274565b80637028e2cd146105b557806370a08231146105d357806379cc6790146106035780637ecebe001461061f5780638456cb591461064f57610274565b80633a46b1a8116101ea578063587cde1e116101ae578063587cde1e146104bb5780635c19a95c146104eb5780635c975abb146105075780635cffe9de14610525578063613255ab146105555780636fcfff451461058557610274565b80633a46b1a8146104195780633f4ba83a1461044957806340c10f191461045357806342966c681461046f5780634ee2cd7e1461048b57610274565b8063248a9ca31161023c578063248a9ca3146103455780632f2ff15d14610375578063313ce567146103915780633644e515146103af57806336568abe146103cd57806339509351146103e957610274565b806301ffc9a71461027957806306fdde03146102a9578063095ea7b3146102c757806318160ddd146102f757806323b872dd14610315575b600080fd5b610293600480360381019061028e9190613cec565b6108df565b6040516102a09190613d34565b60405180910390f35b6102b1610959565b6040516102be9190613ddf565b60405180910390f35b6102e160048036038101906102dc9190613e95565b6109eb565b6040516102ee9190613d34565b60405180910390f35b6102ff610a0e565b60405161030c9190613ee4565b60405180910390f35b61032f600480360381019061032a9190613eff565b610a18565b60405161033c9190613d34565b60405180910390f35b61035f600480360381019061035a9190613f88565b610a47565b60405161036c9190613fc4565b60405180910390f35b61038f600480360381019061038a9190613fdf565b610a67565b005b610399610a88565b6040516103a6919061403b565b60405180910390f35b6103b7610a91565b6040516103c49190613fc4565b60405180910390f35b6103e760048036038101906103e29190613fdf565b610aa0565b005b61040360048036038101906103fe9190613e95565b610b23565b6040516104109190613d34565b60405180910390f35b610433600480360381019061042e9190613e95565b610b5a565b6040516104409190613ee4565b60405180910390f35b610451610bee565b005b61046d60048036038101906104689190613e95565b610c23565b005b61048960048036038101906104849190614056565b610c5c565b005b6104a560048036038101906104a09190613e95565b610c70565b6040516104b29190613ee4565b60405180910390f35b6104d560048036038101906104d09190614083565b610ce0565b6040516104e291906140bf565b60405180910390f35b61050560048036038101906105009190614083565b610d49565b005b61050f610d5d565b60405161051c9190613d34565b60405180910390f35b61053f600480360381019061053a919061417d565b610d74565b60405161054c9190613d34565b60405180910390f35b61056f600480360381019061056a9190614083565b610f61565b60405161057c9190613ee4565b60405180910390f35b61059f600480360381019061059a9190614083565b610fd8565b6040516105ac9190614224565b60405180910390f35b6105bd61102c565b6040516105ca9190613fc4565b60405180910390f35b6105ed60048036038101906105e89190614083565b611050565b6040516105fa9190613ee4565b60405180910390f35b61061d60048036038101906106189190613e95565b611098565b005b61063960048036038101906106349190614083565b6110b8565b6040516106469190613ee4565b60405180910390f35b610657611108565b005b610673600480360381019061066e9190614056565b61113d565b6040516106809190613ee4565b60405180910390f35b6106a3600480360381019061069e9190613fdf565b611193565b6040516106b09190613d34565b60405180910390f35b6106c16111fe565b6040516106ce9190613ddf565b60405180910390f35b6106df611290565b005b6106fb60048036038101906106f69190614056565b6112c6565b6040516107089190613ee4565b60405180910390f35b61072b60048036038101906107269190614083565b6112f7565b6040516107389190613ee4565b60405180910390f35b610749611408565b6040516107569190613fc4565b60405180910390f35b61077960048036038101906107749190613e95565b61140f565b6040516107869190613d34565b60405180910390f35b6107a960048036038101906107a49190613e95565b611486565b6040516107b69190613d34565b60405180910390f35b6107d960048036038101906107d4919061426b565b6114a9565b005b6107f560048036038101906107f091906142f8565b6115ad565b005b6107ff6116ef565b60405161080c9190613fc4565b60405180910390f35b61082f600480360381019061082a9190613fdf565b611713565b005b61084b60048036038101906108469190613e95565b611734565b6040516108589190613ee4565b60405180910390f35b61087b6004803603810190610876919061439a565b6117b6565b6040516108889190613ee4565b60405180910390f35b61089961183d565b6040516108a69190613fc4565b60405180910390f35b6108c960048036038101906108c49190614406565b611861565b6040516108d691906144bb565b60405180910390f35b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610952575061095182611d39565b5b9050919050565b60606003805461096890614505565b80601f016020809104026020016040519081016040528092919081815260200182805461099490614505565b80156109e15780601f106109b6576101008083540402835291602001916109e1565b820191906000526020600020905b8154815290600101906020018083116109c457829003601f168201915b5050505050905090565b6000806109f6611da3565b9050610a03818585611dab565b600191505092915050565b6000600254905090565b600080610a23611da3565b9050610a30858285611f74565b610a3b858585612000565b60019150509392505050565b600060096000838152602001908152602001600020600101549050919050565b610a7082610a47565b610a7981612276565b610a83838361228a565b505050565b60006012905090565b6000610a9b61236b565b905090565b610aa8611da3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0c906145a8565b60405180910390fd5b610b1f8282612485565b5050565b600080610b2e611da3565b9050610b4f818585610b4085896117b6565b610b4a91906145f7565b611dab565b600191505092915050565b6000438210610b9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9590614677565b60405180910390fd5b610be6600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083612567565b905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610c1881612276565b610c206126b8565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610c4d81612276565b610c57838361271b565b505050565b610c6d610c67611da3565b82612729565b50565b6000806000610cbd84600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612737565b9150915081610cd457610ccf85611050565b610cd6565b805b9250505092915050565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610d5a610d54611da3565b8261282c565b50565b6000600a60009054906101000a900460ff16905090565b6000610d7f85610f61565b841115610dc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db890614709565b60405180910390fd5b6000610dcd8686611734565b9050610dd9878661271b565b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd98773ffffffffffffffffffffffffffffffffffffffff166323e30c8b338989868a8a6040518763ffffffff1660e01b8152600401610e3d96959493929190614776565b6020604051808303816000875af1158015610e5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8091906147e7565b14610ec0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb790614886565b60405180910390fd5b6000610eca612946565b9050610ee288308489610edd91906145f7565b611f74565b6000821480610f1d5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b15610f3c57610f37888388610f3291906145f7565b612729565b610f52565b610f468887612729565b610f51888284612000565b5b60019250505095945050505050565b60003073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610f9d576000610fd1565b610fa5610a0e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610fd091906148a6565b5b9050919050565b6000611025600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050611bd5565b9050919050565b7f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f81565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6110aa826110a4611da3565b83611f74565b6110b48282612729565b5050565b6000611101600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d2b565b9050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a61113281612276565b61113a61294b565b50565b6000438210611181576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117890614677565b60405180910390fd5b61118c600f83612567565b9050919050565b60006009600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60606004805461120d90614505565b80601f016020809104026020016040519081016040528092919081815260200182805461123990614505565b80156112865780601f1061125b57610100808354040283529160200191611286565b820191906000526020600020905b81548152906001019060200180831161126957829003601f168201915b5050505050905090565b7f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f6112ba81612276565b6112c26129ae565b5050565b60008060006112d6846006612737565b91509150816112ec576112e7610a0e565b6112ee565b805b92505050919050565b600080600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050600081146113df57600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060018261139391906148a6565b815481106113a4576113a36148da565b5b9060005260206000200160000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166113e2565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16915050919050565b6000801b81565b60008061141a611da3565b9050600061142882866117b6565b90508381101561146d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114649061497b565b60405180910390fd5b61147a8286868403611dab565b60019250505092915050565b600080611491611da3565b905061149e818585612000565b600191505092915050565b834211156114ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e3906149e7565b60405180910390fd5b600061154e6115467fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf89898960405160200161152b9493929190614a07565b60405160208183030381529060405280519060200120612a04565b858585612a1e565b905061155981612a49565b861461159a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161159190614a98565b60405180910390fd5b6115a4818861282c565b50505050505050565b834211156115f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115e790614b04565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861161f8c612a49565b8960405160200161163596959493929190614b24565b604051602081830303815290604052805190602001209050600061165882612a04565b9050600061166882878787612a1e565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146116d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116cf90614bd1565b60405180910390fd5b6116e38a8a8a611dab565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61171c82610a47565b61172581612276565b61172f8383612485565b505050565b60003073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146117a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179b90614c3d565b60405180910390fd5b6117ae8383612aa7565b905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b611869613c4c565b600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208263ffffffff16815481106118c0576118bf6148da565b5b906000526020600020016040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050905092915050565b61197b82826119fe565b611983612aaf565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166119a9610a0e565b11156119ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e190614ccf565b60405180910390fd5b6119f8600f611b5483612ad3565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a6d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6490614d3b565b60405180910390fd5b611a7960008383612da2565b8060026000828254611a8b91906145f7565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611b3c9190613ee4565b60405180910390a3611b5060008383612dba565b5050565b60008183611b6291906145f7565b905092915050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8016821115611bcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc490614dcd565b60405180910390fd5b819050919050565b600063ffffffff8016821115611c20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1790614e5f565b60405180910390fd5b819050919050565b611c33838383611d0b565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611c7d57611c7082612dca565b611c78612e1d565b611cdb565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611cc757611cba83612dca565b611cc2612e1d565b611cda565b611cd083612dca565b611cd982612dca565b5b5b505050565b611ceb838383611d10565b611d06611cf784610ce0565b611d0084610ce0565b83612e31565b505050565b505050565b505050565b60008183611d2391906148a6565b905092915050565b600081600001549050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611e1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1190614ef1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8090614f83565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051611f679190613ee4565b60405180910390a3505050565b6000611f8084846117b6565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611ffa5781811015611fec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fe390614fef565b60405180910390fd5b611ff98484848403611dab565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361206f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206690615081565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036120de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120d590615113565b60405180910390fd5b6120e9838383612da2565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561216f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612166906151a5565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161225d9190613ee4565b60405180910390a3612270848484612dba565b50505050565b61228781612282611da3565b61302a565b50565b6122948282611193565b6123675760016009600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061230c611da3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480156123e757507f000000000000000000000000000000000000000000000000000000000000000046145b15612414577f00000000000000000000000000000000000000000000000000000000000000009050612482565b61247f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006130af565b90505b90565b61248f8282611193565b156125635760006009600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612508611da3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000808380549050905060008082905060058311156125dd57600061258b846130e9565b8461259691906148a6565b9050856125a388836131e2565b60000160009054906101000a900463ffffffff1663ffffffff1611156125cb578091506125db565b6001816125d891906145f7565b92505b505b5b8082101561263d5760006125f283836131f7565b9050856125ff88836131e2565b60000160009054906101000a900463ffffffff1663ffffffff16111561262757809150612637565b60018161263491906145f7565b92505b506125de565b6000811461268c5761265b8660018361265691906148a6565b6131e2565b60000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661268f565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16935050505092915050565b6126c061321d565b6000600a60006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612704611da3565b60405161271191906140bf565b60405180910390a1565b6127258282611971565b5050565b6127338282613266565b5050565b6000806000841161277d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161277490615211565b60405180910390fd5b612785613284565b8411156127c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127be9061527d565b60405180910390fd5b60006127df858560000161329590919063ffffffff16565b9050836000018054905081036127fc576000809250925050612825565b6001846001018281548110612814576128136148da565b5b906000526020600020015492509250505b9250929050565b600061283783610ce0565b9050600061284484611050565b905082600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a4612940828483612e31565b50505050565b600090565b61295361334e565b6001600a60006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612997611da3565b6040516129a491906140bf565b60405180910390a1565b60006129ba6008613398565b60006129c4613284565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67816040516129f59190613ee4565b60405180910390a18091505090565b6000612a17612a1161236b565b836133ae565b9050919050565b6000806000612a2f878787876133e1565b91509150612a3c816134c3565b8192505050949350505050565b600080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050612a9681611d2b565b9150612aa181613398565b50919050565b600092915050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b6000806000858054905090506000808214612ba257612afe87600184612af991906148a6565b6131e2565b6040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050612bde565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152505b905080602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169350612c1384868863ffffffff16565b9250600082118015612c2e575043816000015163ffffffff16145b15612ca857612c3c83611b6a565b612c5288600185612c4d91906148a6565b6131e2565b60000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550612d98565b866040518060400160405280612cbd43611bd5565b63ffffffff168152602001612cd186611b6a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555050505b5050935093915050565b612daa61334e565b612db5838383611c28565b505050565b612dc5838383611ce0565b505050565b612e1a600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612e1583611050565b613629565b50565b612e2f6006612e2a610a0e565b613629565b565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612e6d5750600081115b1561302557600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612f4b57600080612ef4600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d1585612ad3565b915091508473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051612f4092919061529d565b60405180910390a250505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461302457600080612fcd600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611b5485612ad3565b915091508373ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405161301992919061529d565b60405180910390a250505b5b505050565b6130348282611193565b6130ab57613041816136a4565b61304f8360001c60206136d1565b60405160200161306092919061539a565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a29190613ddf565b60405180910390fd5b5050565b600083838346306040516020016130ca9594939291906153d4565b6040516020818303038152906040528051906020012090509392505050565b60008082036130fb57600090506131dd565b600060016131088461390d565b901c6001901b9050600181848161312257613121615427565b5b048201901c9050600181848161313b5761313a615427565b5b048201901c9050600181848161315457613153615427565b5b048201901c9050600181848161316d5761316c615427565b5b048201901c9050600181848161318657613185615427565b5b048201901c9050600181848161319f5761319e615427565b5b048201901c905060018184816131b8576131b7615427565b5b048201901c90506131d9818285816131d3576131d2615427565b5b046139ee565b9150505b919050565b60008260005281602060002001905092915050565b600060028284186132089190615456565b82841661321591906145f7565b905092915050565b613225610d5d565b613264576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161325b906154d3565b60405180910390fd5b565b6132708282613a07565b61327e600f611d1583612ad3565b50505050565b60006132906008611d2b565b905090565b6000808380549050036132ab5760009050613348565b600080848054905090505b808210156132ff5760006132ca83836131f7565b9050846132d78783613bd4565b6000015411156132e9578091506132f9565b6001816132f691906145f7565b92505b506132b6565b6000821180156133275750836133218660018561331c91906148a6565b613bd4565b60000154145b156133425760018261333991906148a6565b92505050613348565b81925050505b92915050565b613356610d5d565b15613396576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161338d9061553f565b60405180910390fd5b565b6001816000016000828254019250508190555050565b600082826040516020016133c39291906155cc565b60405160208183030381529060405280519060200120905092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c111561341c5760006003915091506134ba565b6000600187878787604051600081526020016040526040516134419493929190615603565b6020604051602081039080840390855afa158015613463573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036134b1576000600192509250506134ba565b80600092509250505b94509492505050565b600060048111156134d7576134d6615648565b5b8160048111156134ea576134e9615648565b5b0315613626576001600481111561350457613503615648565b5b81600481111561351757613516615648565b5b03613557576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161354e906156c3565b60405180910390fd5b6002600481111561356b5761356a615648565b5b81600481111561357e5761357d615648565b5b036135be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135b59061572f565b60405180910390fd5b600360048111156135d2576135d1615648565b5b8160048111156135e5576135e4615648565b5b03613625576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161361c906157c1565b60405180910390fd5b5b50565b6000613633613284565b90508061364284600001613bf6565b101561369f5782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b60606136ca8273ffffffffffffffffffffffffffffffffffffffff16601460ff166136d1565b9050919050565b6060600060028360026136e491906157e1565b6136ee91906145f7565b67ffffffffffffffff81111561370757613706615823565b5b6040519080825280601f01601f1916602001820160405280156137395781602001600182028036833780820191505090505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613771576137706148da565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106137d5576137d46148da565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000600184600261381591906157e1565b61381f91906145f7565b90505b60018111156138bf577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110613861576138606148da565b5b1a60f81b828281518110613878576138776148da565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806138b890615852565b9050613822565b5060008414613903576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138fa906158c7565b60405180910390fd5b8091505092915050565b600080600090506000608084901c111561392f57608083901c92506080810190505b6000604084901c111561394a57604083901c92506040810190505b6000602084901c111561396557602083901c92506020810190505b6000601084901c111561398057601083901c92506010810190505b6000600884901c111561399b57600883901c92506008810190505b6000600484901c11156139b657600483901c92506004810190505b6000600284901c11156139d157600283901c92506002810190505b6000600184901c11156139e5576001810190505b80915050919050565b60008183106139fd57816139ff565b825b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613a76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a6d90615959565b60405180910390fd5b613a8282600083612da2565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015613b08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613aff906159eb565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008282540392505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613bbb9190613ee4565b60405180910390a3613bcf83600084612dba565b505050565b60008083600052826020600020019050613bed81613c42565b91505092915050565b600080828054905003613c0c5760009050613c3d565b8160018380549050613c1e91906148a6565b81548110613c2f57613c2e6148da565b5b906000526020600020015490505b919050565b6000819050919050565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613cc981613c94565b8114613cd457600080fd5b50565b600081359050613ce681613cc0565b92915050565b600060208284031215613d0257613d01613c8a565b5b6000613d1084828501613cd7565b91505092915050565b60008115159050919050565b613d2e81613d19565b82525050565b6000602082019050613d496000830184613d25565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613d89578082015181840152602081019050613d6e565b60008484015250505050565b6000601f19601f8301169050919050565b6000613db182613d4f565b613dbb8185613d5a565b9350613dcb818560208601613d6b565b613dd481613d95565b840191505092915050565b60006020820190508181036000830152613df98184613da6565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613e2c82613e01565b9050919050565b613e3c81613e21565b8114613e4757600080fd5b50565b600081359050613e5981613e33565b92915050565b6000819050919050565b613e7281613e5f565b8114613e7d57600080fd5b50565b600081359050613e8f81613e69565b92915050565b60008060408385031215613eac57613eab613c8a565b5b6000613eba85828601613e4a565b9250506020613ecb85828601613e80565b9150509250929050565b613ede81613e5f565b82525050565b6000602082019050613ef96000830184613ed5565b92915050565b600080600060608486031215613f1857613f17613c8a565b5b6000613f2686828701613e4a565b9350506020613f3786828701613e4a565b9250506040613f4886828701613e80565b9150509250925092565b6000819050919050565b613f6581613f52565b8114613f7057600080fd5b50565b600081359050613f8281613f5c565b92915050565b600060208284031215613f9e57613f9d613c8a565b5b6000613fac84828501613f73565b91505092915050565b613fbe81613f52565b82525050565b6000602082019050613fd96000830184613fb5565b92915050565b60008060408385031215613ff657613ff5613c8a565b5b600061400485828601613f73565b925050602061401585828601613e4a565b9150509250929050565b600060ff82169050919050565b6140358161401f565b82525050565b6000602082019050614050600083018461402c565b92915050565b60006020828403121561406c5761406b613c8a565b5b600061407a84828501613e80565b91505092915050565b60006020828403121561409957614098613c8a565b5b60006140a784828501613e4a565b91505092915050565b6140b981613e21565b82525050565b60006020820190506140d460008301846140b0565b92915050565b60006140e582613e21565b9050919050565b6140f5816140da565b811461410057600080fd5b50565b600081359050614112816140ec565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261413d5761413c614118565b5b8235905067ffffffffffffffff81111561415a5761415961411d565b5b60208301915083600182028301111561417657614175614122565b5b9250929050565b60008060008060006080868803121561419957614198613c8a565b5b60006141a788828901614103565b95505060206141b888828901613e4a565b94505060406141c988828901613e80565b935050606086013567ffffffffffffffff8111156141ea576141e9613c8f565b5b6141f688828901614127565b92509250509295509295909350565b600063ffffffff82169050919050565b61421e81614205565b82525050565b60006020820190506142396000830184614215565b92915050565b6142488161401f565b811461425357600080fd5b50565b6000813590506142658161423f565b92915050565b60008060008060008060c0878903121561428857614287613c8a565b5b600061429689828a01613e4a565b96505060206142a789828a01613e80565b95505060406142b889828a01613e80565b94505060606142c989828a01614256565b93505060806142da89828a01613f73565b92505060a06142eb89828a01613f73565b9150509295509295509295565b600080600080600080600060e0888a03121561431757614316613c8a565b5b60006143258a828b01613e4a565b97505060206143368a828b01613e4a565b96505060406143478a828b01613e80565b95505060606143588a828b01613e80565b94505060806143698a828b01614256565b93505060a061437a8a828b01613f73565b92505060c061438b8a828b01613f73565b91505092959891949750929550565b600080604083850312156143b1576143b0613c8a565b5b60006143bf85828601613e4a565b92505060206143d085828601613e4a565b9150509250929050565b6143e381614205565b81146143ee57600080fd5b50565b600081359050614400816143da565b92915050565b6000806040838503121561441d5761441c613c8a565b5b600061442b85828601613e4a565b925050602061443c858286016143f1565b9150509250929050565b61444f81614205565b82525050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b61448681614455565b82525050565b6040820160008201516144a26000850182614446565b5060208201516144b5602085018261447d565b50505050565b60006040820190506144d0600083018461448c565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061451d57607f821691505b6020821081036145305761452f6144d6565b5b50919050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b6000614592602f83613d5a565b915061459d82614536565b604082019050919050565b600060208201905081810360008301526145c181614585565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061460282613e5f565b915061460d83613e5f565b9250828201905080821115614625576146246145c8565b5b92915050565b7f4552433230566f7465733a20626c6f636b206e6f7420796574206d696e656400600082015250565b6000614661601f83613d5a565b915061466c8261462b565b602082019050919050565b6000602082019050818103600083015261469081614654565b9050919050565b7f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60008201527f6178466c6173684c6f616e000000000000000000000000000000000000000000602082015250565b60006146f3602b83613d5a565b91506146fe82614697565b604082019050919050565b60006020820190508181036000830152614722816146e6565b9050919050565b600082825260208201905092915050565b82818337600083830152505050565b60006147558385614729565b935061476283858461473a565b61476b83613d95565b840190509392505050565b600060a08201905061478b60008301896140b0565b61479860208301886140b0565b6147a56040830187613ed5565b6147b26060830186613ed5565b81810360808301526147c5818486614749565b9050979650505050505050565b6000815190506147e181613f5c565b92915050565b6000602082840312156147fd576147fc613c8a565b5b600061480b848285016147d2565b91505092915050565b7f4552433230466c6173684d696e743a20696e76616c69642072657475726e207660008201527f616c756500000000000000000000000000000000000000000000000000000000602082015250565b6000614870602483613d5a565b915061487b82614814565b604082019050919050565b6000602082019050818103600083015261489f81614863565b9050919050565b60006148b182613e5f565b91506148bc83613e5f565b92508282039050818111156148d4576148d36145c8565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000614965602583613d5a565b915061497082614909565b604082019050919050565b6000602082019050818103600083015261499481614958565b9050919050565b7f4552433230566f7465733a207369676e61747572652065787069726564000000600082015250565b60006149d1601d83613d5a565b91506149dc8261499b565b602082019050919050565b60006020820190508181036000830152614a00816149c4565b9050919050565b6000608082019050614a1c6000830187613fb5565b614a2960208301866140b0565b614a366040830185613ed5565b614a436060830184613ed5565b95945050505050565b7f4552433230566f7465733a20696e76616c6964206e6f6e636500000000000000600082015250565b6000614a82601983613d5a565b9150614a8d82614a4c565b602082019050919050565b60006020820190508181036000830152614ab181614a75565b9050919050565b7f45524332305065726d69743a206578706972656420646561646c696e65000000600082015250565b6000614aee601d83613d5a565b9150614af982614ab8565b602082019050919050565b60006020820190508181036000830152614b1d81614ae1565b9050919050565b600060c082019050614b396000830189613fb5565b614b4660208301886140b0565b614b5360408301876140b0565b614b606060830186613ed5565b614b6d6080830185613ed5565b614b7a60a0830184613ed5565b979650505050505050565b7f45524332305065726d69743a20696e76616c6964207369676e61747572650000600082015250565b6000614bbb601e83613d5a565b9150614bc682614b85565b602082019050919050565b60006020820190508181036000830152614bea81614bae565b9050919050565b7f4552433230466c6173684d696e743a2077726f6e6720746f6b656e0000000000600082015250565b6000614c27601b83613d5a565b9150614c3282614bf1565b602082019050919050565b60006020820190508181036000830152614c5681614c1a565b9050919050565b7f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60008201527f766572666c6f77696e6720766f74657300000000000000000000000000000000602082015250565b6000614cb9603083613d5a565b9150614cc482614c5d565b604082019050919050565b60006020820190508181036000830152614ce881614cac565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b6000614d25601f83613d5a565b9150614d3082614cef565b602082019050919050565b60006020820190508181036000830152614d5481614d18565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203260008201527f3234206269747300000000000000000000000000000000000000000000000000602082015250565b6000614db7602783613d5a565b9150614dc282614d5b565b604082019050919050565b60006020820190508181036000830152614de681614daa565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203360008201527f3220626974730000000000000000000000000000000000000000000000000000602082015250565b6000614e49602683613d5a565b9150614e5482614ded565b604082019050919050565b60006020820190508181036000830152614e7881614e3c565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000614edb602483613d5a565b9150614ee682614e7f565b604082019050919050565b60006020820190508181036000830152614f0a81614ece565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b6000614f6d602283613d5a565b9150614f7882614f11565b604082019050919050565b60006020820190508181036000830152614f9c81614f60565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b6000614fd9601d83613d5a565b9150614fe482614fa3565b602082019050919050565b6000602082019050818103600083015261500881614fcc565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b600061506b602583613d5a565b91506150768261500f565b604082019050919050565b6000602082019050818103600083015261509a8161505e565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b60006150fd602383613d5a565b9150615108826150a1565b604082019050919050565b6000602082019050818103600083015261512c816150f0565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b600061518f602683613d5a565b915061519a82615133565b604082019050919050565b600060208201905081810360008301526151be81615182565b9050919050565b7f4552433230536e617073686f743a206964206973203000000000000000000000600082015250565b60006151fb601683613d5a565b9150615206826151c5565b602082019050919050565b6000602082019050818103600083015261522a816151ee565b9050919050565b7f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000600082015250565b6000615267601d83613d5a565b915061527282615231565b602082019050919050565b600060208201905081810360008301526152968161525a565b9050919050565b60006040820190506152b26000830185613ed5565b6152bf6020830184613ed5565b9392505050565b600081905092915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006153076017836152c6565b9150615312826152d1565b601782019050919050565b600061532882613d4f565b61533281856152c6565b9350615342818560208601613d6b565b80840191505092915050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b60006153846011836152c6565b915061538f8261534e565b601182019050919050565b60006153a5826152fa565b91506153b1828561531d565b91506153bc82615377565b91506153c8828461531d565b91508190509392505050565b600060a0820190506153e96000830188613fb5565b6153f66020830187613fb5565b6154036040830186613fb5565b6154106060830185613ed5565b61541d60808301846140b0565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061546182613e5f565b915061546c83613e5f565b92508261547c5761547b615427565b5b828204905092915050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006154bd601483613d5a565b91506154c882615487565b602082019050919050565b600060208201905081810360008301526154ec816154b0565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000615529601083613d5a565b9150615534826154f3565b602082019050919050565b600060208201905081810360008301526155588161551c565b9050919050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b60006155956002836152c6565b91506155a08261555f565b600282019050919050565b6000819050919050565b6155c66155c182613f52565b6155ab565b82525050565b60006155d782615588565b91506155e382856155b5565b6020820191506155f382846155b5565b6020820191508190509392505050565b60006080820190506156186000830187613fb5565b615625602083018661402c565b6156326040830185613fb5565b61563f6060830184613fb5565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b60006156ad601883613d5a565b91506156b882615677565b602082019050919050565b600060208201905081810360008301526156dc816156a0565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615719601f83613d5a565b9150615724826156e3565b602082019050919050565b600060208201905081810360008301526157488161570c565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b60006157ab602283613d5a565b91506157b68261574f565b604082019050919050565b600060208201905081810360008301526157da8161579e565b9050919050565b60006157ec82613e5f565b91506157f783613e5f565b925082820261580581613e5f565b9150828204841483151761581c5761581b6145c8565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061585d82613e5f565b9150600082036158705761586f6145c8565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006158b1602083613d5a565b91506158bc8261587b565b602082019050919050565b600060208201905081810360008301526158e0816158a4565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b6000615943602183613d5a565b915061594e826158e7565b604082019050919050565b6000602082019050818103600083015261597281615936565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b60006159d5602283613d5a565b91506159e082615979565b604082019050919050565b60006020820190508181036000830152615a04816159c8565b905091905056fea2646970667358221220c004ab49ae258f385157b7351af018d745305cd9613cbe87b316ed098632674a64736f6c63430008120033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102745760003560e01c80637028e2cd11610151578063a217fddf116100c3578063d539139311610087578063d5391393146107f7578063d547741f14610815578063d9d98ce414610831578063dd62ed3e14610861578063e63ab1e914610891578063f1127ed8146108af57610274565b8063a217fddf14610741578063a457c2d71461075f578063a9059cbb1461078f578063c3cda520146107bf578063d505accf146107db57610274565b80638e539e8c116101155780638e539e8c1461065957806391d148541461068957806395d89b41146106b95780639711715a146106d7578063981b24d0146106e15780639ab24eb01461071157610274565b80637028e2cd146105b557806370a08231146105d357806379cc6790146106035780637ecebe001461061f5780638456cb591461064f57610274565b80633a46b1a8116101ea578063587cde1e116101ae578063587cde1e146104bb5780635c19a95c146104eb5780635c975abb146105075780635cffe9de14610525578063613255ab146105555780636fcfff451461058557610274565b80633a46b1a8146104195780633f4ba83a1461044957806340c10f191461045357806342966c681461046f5780634ee2cd7e1461048b57610274565b8063248a9ca31161023c578063248a9ca3146103455780632f2ff15d14610375578063313ce567146103915780633644e515146103af57806336568abe146103cd57806339509351146103e957610274565b806301ffc9a71461027957806306fdde03146102a9578063095ea7b3146102c757806318160ddd146102f757806323b872dd14610315575b600080fd5b610293600480360381019061028e9190613cec565b6108df565b6040516102a09190613d34565b60405180910390f35b6102b1610959565b6040516102be9190613ddf565b60405180910390f35b6102e160048036038101906102dc9190613e95565b6109eb565b6040516102ee9190613d34565b60405180910390f35b6102ff610a0e565b60405161030c9190613ee4565b60405180910390f35b61032f600480360381019061032a9190613eff565b610a18565b60405161033c9190613d34565b60405180910390f35b61035f600480360381019061035a9190613f88565b610a47565b60405161036c9190613fc4565b60405180910390f35b61038f600480360381019061038a9190613fdf565b610a67565b005b610399610a88565b6040516103a6919061403b565b60405180910390f35b6103b7610a91565b6040516103c49190613fc4565b60405180910390f35b6103e760048036038101906103e29190613fdf565b610aa0565b005b61040360048036038101906103fe9190613e95565b610b23565b6040516104109190613d34565b60405180910390f35b610433600480360381019061042e9190613e95565b610b5a565b6040516104409190613ee4565b60405180910390f35b610451610bee565b005b61046d60048036038101906104689190613e95565b610c23565b005b61048960048036038101906104849190614056565b610c5c565b005b6104a560048036038101906104a09190613e95565b610c70565b6040516104b29190613ee4565b60405180910390f35b6104d560048036038101906104d09190614083565b610ce0565b6040516104e291906140bf565b60405180910390f35b61050560048036038101906105009190614083565b610d49565b005b61050f610d5d565b60405161051c9190613d34565b60405180910390f35b61053f600480360381019061053a919061417d565b610d74565b60405161054c9190613d34565b60405180910390f35b61056f600480360381019061056a9190614083565b610f61565b60405161057c9190613ee4565b60405180910390f35b61059f600480360381019061059a9190614083565b610fd8565b6040516105ac9190614224565b60405180910390f35b6105bd61102c565b6040516105ca9190613fc4565b60405180910390f35b6105ed60048036038101906105e89190614083565b611050565b6040516105fa9190613ee4565b60405180910390f35b61061d60048036038101906106189190613e95565b611098565b005b61063960048036038101906106349190614083565b6110b8565b6040516106469190613ee4565b60405180910390f35b610657611108565b005b610673600480360381019061066e9190614056565b61113d565b6040516106809190613ee4565b60405180910390f35b6106a3600480360381019061069e9190613fdf565b611193565b6040516106b09190613d34565b60405180910390f35b6106c16111fe565b6040516106ce9190613ddf565b60405180910390f35b6106df611290565b005b6106fb60048036038101906106f69190614056565b6112c6565b6040516107089190613ee4565b60405180910390f35b61072b60048036038101906107269190614083565b6112f7565b6040516107389190613ee4565b60405180910390f35b610749611408565b6040516107569190613fc4565b60405180910390f35b61077960048036038101906107749190613e95565b61140f565b6040516107869190613d34565b60405180910390f35b6107a960048036038101906107a49190613e95565b611486565b6040516107b69190613d34565b60405180910390f35b6107d960048036038101906107d4919061426b565b6114a9565b005b6107f560048036038101906107f091906142f8565b6115ad565b005b6107ff6116ef565b60405161080c9190613fc4565b60405180910390f35b61082f600480360381019061082a9190613fdf565b611713565b005b61084b60048036038101906108469190613e95565b611734565b6040516108589190613ee4565b60405180910390f35b61087b6004803603810190610876919061439a565b6117b6565b6040516108889190613ee4565b60405180910390f35b61089961183d565b6040516108a69190613fc4565b60405180910390f35b6108c960048036038101906108c49190614406565b611861565b6040516108d691906144bb565b60405180910390f35b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610952575061095182611d39565b5b9050919050565b60606003805461096890614505565b80601f016020809104026020016040519081016040528092919081815260200182805461099490614505565b80156109e15780601f106109b6576101008083540402835291602001916109e1565b820191906000526020600020905b8154815290600101906020018083116109c457829003601f168201915b5050505050905090565b6000806109f6611da3565b9050610a03818585611dab565b600191505092915050565b6000600254905090565b600080610a23611da3565b9050610a30858285611f74565b610a3b858585612000565b60019150509392505050565b600060096000838152602001908152602001600020600101549050919050565b610a7082610a47565b610a7981612276565b610a83838361228a565b505050565b60006012905090565b6000610a9b61236b565b905090565b610aa8611da3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0c906145a8565b60405180910390fd5b610b1f8282612485565b5050565b600080610b2e611da3565b9050610b4f818585610b4085896117b6565b610b4a91906145f7565b611dab565b600191505092915050565b6000438210610b9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9590614677565b60405180910390fd5b610be6600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083612567565b905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610c1881612276565b610c206126b8565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610c4d81612276565b610c57838361271b565b505050565b610c6d610c67611da3565b82612729565b50565b6000806000610cbd84600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612737565b9150915081610cd457610ccf85611050565b610cd6565b805b9250505092915050565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610d5a610d54611da3565b8261282c565b50565b6000600a60009054906101000a900460ff16905090565b6000610d7f85610f61565b841115610dc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db890614709565b60405180910390fd5b6000610dcd8686611734565b9050610dd9878661271b565b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd98773ffffffffffffffffffffffffffffffffffffffff166323e30c8b338989868a8a6040518763ffffffff1660e01b8152600401610e3d96959493929190614776565b6020604051808303816000875af1158015610e5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8091906147e7565b14610ec0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb790614886565b60405180910390fd5b6000610eca612946565b9050610ee288308489610edd91906145f7565b611f74565b6000821480610f1d5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b15610f3c57610f37888388610f3291906145f7565b612729565b610f52565b610f468887612729565b610f51888284612000565b5b60019250505095945050505050565b60003073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610f9d576000610fd1565b610fa5610a0e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610fd091906148a6565b5b9050919050565b6000611025600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050611bd5565b9050919050565b7f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f81565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6110aa826110a4611da3565b83611f74565b6110b48282612729565b5050565b6000611101600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d2b565b9050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a61113281612276565b61113a61294b565b50565b6000438210611181576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117890614677565b60405180910390fd5b61118c600f83612567565b9050919050565b60006009600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60606004805461120d90614505565b80601f016020809104026020016040519081016040528092919081815260200182805461123990614505565b80156112865780601f1061125b57610100808354040283529160200191611286565b820191906000526020600020905b81548152906001019060200180831161126957829003601f168201915b5050505050905090565b7f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f6112ba81612276565b6112c26129ae565b5050565b60008060006112d6846006612737565b91509150816112ec576112e7610a0e565b6112ee565b805b92505050919050565b600080600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050600081146113df57600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060018261139391906148a6565b815481106113a4576113a36148da565b5b9060005260206000200160000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166113e2565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16915050919050565b6000801b81565b60008061141a611da3565b9050600061142882866117b6565b90508381101561146d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114649061497b565b60405180910390fd5b61147a8286868403611dab565b60019250505092915050565b600080611491611da3565b905061149e818585612000565b600191505092915050565b834211156114ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e3906149e7565b60405180910390fd5b600061154e6115467fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf89898960405160200161152b9493929190614a07565b60405160208183030381529060405280519060200120612a04565b858585612a1e565b905061155981612a49565b861461159a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161159190614a98565b60405180910390fd5b6115a4818861282c565b50505050505050565b834211156115f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115e790614b04565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861161f8c612a49565b8960405160200161163596959493929190614b24565b604051602081830303815290604052805190602001209050600061165882612a04565b9050600061166882878787612a1e565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146116d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116cf90614bd1565b60405180910390fd5b6116e38a8a8a611dab565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61171c82610a47565b61172581612276565b61172f8383612485565b505050565b60003073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146117a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179b90614c3d565b60405180910390fd5b6117ae8383612aa7565b905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b611869613c4c565b600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208263ffffffff16815481106118c0576118bf6148da565b5b906000526020600020016040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050905092915050565b61197b82826119fe565b611983612aaf565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166119a9610a0e565b11156119ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e190614ccf565b60405180910390fd5b6119f8600f611b5483612ad3565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a6d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6490614d3b565b60405180910390fd5b611a7960008383612da2565b8060026000828254611a8b91906145f7565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611b3c9190613ee4565b60405180910390a3611b5060008383612dba565b5050565b60008183611b6291906145f7565b905092915050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8016821115611bcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc490614dcd565b60405180910390fd5b819050919050565b600063ffffffff8016821115611c20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1790614e5f565b60405180910390fd5b819050919050565b611c33838383611d0b565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611c7d57611c7082612dca565b611c78612e1d565b611cdb565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611cc757611cba83612dca565b611cc2612e1d565b611cda565b611cd083612dca565b611cd982612dca565b5b5b505050565b611ceb838383611d10565b611d06611cf784610ce0565b611d0084610ce0565b83612e31565b505050565b505050565b505050565b60008183611d2391906148a6565b905092915050565b600081600001549050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611e1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1190614ef1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8090614f83565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051611f679190613ee4565b60405180910390a3505050565b6000611f8084846117b6565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611ffa5781811015611fec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fe390614fef565b60405180910390fd5b611ff98484848403611dab565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361206f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206690615081565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036120de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120d590615113565b60405180910390fd5b6120e9838383612da2565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561216f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612166906151a5565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161225d9190613ee4565b60405180910390a3612270848484612dba565b50505050565b61228781612282611da3565b61302a565b50565b6122948282611193565b6123675760016009600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061230c611da3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60007f0000000000000000000000006a3a8a31666e281a4fb50c862dd7a997ca4bee1673ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480156123e757507f000000000000000000000000000000000000000000000000000000000000000146145b15612414577f20413a469f67340b39c582627ec090031c2dc2b9353977c9ef1710ab14d3cbf89050612482565b61247f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f4bb259d82788938ff1df59298ccef1c8352431150630e9fb3e4cffb8deb25f767fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66130af565b90505b90565b61248f8282611193565b156125635760006009600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612508611da3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000808380549050905060008082905060058311156125dd57600061258b846130e9565b8461259691906148a6565b9050856125a388836131e2565b60000160009054906101000a900463ffffffff1663ffffffff1611156125cb578091506125db565b6001816125d891906145f7565b92505b505b5b8082101561263d5760006125f283836131f7565b9050856125ff88836131e2565b60000160009054906101000a900463ffffffff1663ffffffff16111561262757809150612637565b60018161263491906145f7565b92505b506125de565b6000811461268c5761265b8660018361265691906148a6565b6131e2565b60000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661268f565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16935050505092915050565b6126c061321d565b6000600a60006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612704611da3565b60405161271191906140bf565b60405180910390a1565b6127258282611971565b5050565b6127338282613266565b5050565b6000806000841161277d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161277490615211565b60405180910390fd5b612785613284565b8411156127c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127be9061527d565b60405180910390fd5b60006127df858560000161329590919063ffffffff16565b9050836000018054905081036127fc576000809250925050612825565b6001846001018281548110612814576128136148da565b5b906000526020600020015492509250505b9250929050565b600061283783610ce0565b9050600061284484611050565b905082600d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a4612940828483612e31565b50505050565b600090565b61295361334e565b6001600a60006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612997611da3565b6040516129a491906140bf565b60405180910390a1565b60006129ba6008613398565b60006129c4613284565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67816040516129f59190613ee4565b60405180910390a18091505090565b6000612a17612a1161236b565b836133ae565b9050919050565b6000806000612a2f878787876133e1565b91509150612a3c816134c3565b8192505050949350505050565b600080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050612a9681611d2b565b9150612aa181613398565b50919050565b600092915050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b6000806000858054905090506000808214612ba257612afe87600184612af991906148a6565b6131e2565b6040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525050612bde565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152505b905080602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169350612c1384868863ffffffff16565b9250600082118015612c2e575043816000015163ffffffff16145b15612ca857612c3c83611b6a565b612c5288600185612c4d91906148a6565b6131e2565b60000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550612d98565b866040518060400160405280612cbd43611bd5565b63ffffffff168152602001612cd186611b6a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555050505b5050935093915050565b612daa61334e565b612db5838383611c28565b505050565b612dc5838383611ce0565b505050565b612e1a600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612e1583611050565b613629565b50565b612e2f6006612e2a610a0e565b613629565b565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612e6d5750600081115b1561302557600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612f4b57600080612ef4600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d1585612ad3565b915091508473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051612f4092919061529d565b60405180910390a250505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461302457600080612fcd600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611b5485612ad3565b915091508373ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405161301992919061529d565b60405180910390a250505b5b505050565b6130348282611193565b6130ab57613041816136a4565b61304f8360001c60206136d1565b60405160200161306092919061539a565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a29190613ddf565b60405180910390fd5b5050565b600083838346306040516020016130ca9594939291906153d4565b6040516020818303038152906040528051906020012090509392505050565b60008082036130fb57600090506131dd565b600060016131088461390d565b901c6001901b9050600181848161312257613121615427565b5b048201901c9050600181848161313b5761313a615427565b5b048201901c9050600181848161315457613153615427565b5b048201901c9050600181848161316d5761316c615427565b5b048201901c9050600181848161318657613185615427565b5b048201901c9050600181848161319f5761319e615427565b5b048201901c905060018184816131b8576131b7615427565b5b048201901c90506131d9818285816131d3576131d2615427565b5b046139ee565b9150505b919050565b60008260005281602060002001905092915050565b600060028284186132089190615456565b82841661321591906145f7565b905092915050565b613225610d5d565b613264576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161325b906154d3565b60405180910390fd5b565b6132708282613a07565b61327e600f611d1583612ad3565b50505050565b60006132906008611d2b565b905090565b6000808380549050036132ab5760009050613348565b600080848054905090505b808210156132ff5760006132ca83836131f7565b9050846132d78783613bd4565b6000015411156132e9578091506132f9565b6001816132f691906145f7565b92505b506132b6565b6000821180156133275750836133218660018561331c91906148a6565b613bd4565b60000154145b156133425760018261333991906148a6565b92505050613348565b81925050505b92915050565b613356610d5d565b15613396576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161338d9061553f565b60405180910390fd5b565b6001816000016000828254019250508190555050565b600082826040516020016133c39291906155cc565b60405160208183030381529060405280519060200120905092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c111561341c5760006003915091506134ba565b6000600187878787604051600081526020016040526040516134419493929190615603565b6020604051602081039080840390855afa158015613463573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036134b1576000600192509250506134ba565b80600092509250505b94509492505050565b600060048111156134d7576134d6615648565b5b8160048111156134ea576134e9615648565b5b0315613626576001600481111561350457613503615648565b5b81600481111561351757613516615648565b5b03613557576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161354e906156c3565b60405180910390fd5b6002600481111561356b5761356a615648565b5b81600481111561357e5761357d615648565b5b036135be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135b59061572f565b60405180910390fd5b600360048111156135d2576135d1615648565b5b8160048111156135e5576135e4615648565b5b03613625576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161361c906157c1565b60405180910390fd5b5b50565b6000613633613284565b90508061364284600001613bf6565b101561369f5782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b60606136ca8273ffffffffffffffffffffffffffffffffffffffff16601460ff166136d1565b9050919050565b6060600060028360026136e491906157e1565b6136ee91906145f7565b67ffffffffffffffff81111561370757613706615823565b5b6040519080825280601f01601f1916602001820160405280156137395781602001600182028036833780820191505090505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613771576137706148da565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106137d5576137d46148da565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000600184600261381591906157e1565b61381f91906145f7565b90505b60018111156138bf577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110613861576138606148da565b5b1a60f81b828281518110613878576138776148da565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806138b890615852565b9050613822565b5060008414613903576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138fa906158c7565b60405180910390fd5b8091505092915050565b600080600090506000608084901c111561392f57608083901c92506080810190505b6000604084901c111561394a57604083901c92506040810190505b6000602084901c111561396557602083901c92506020810190505b6000601084901c111561398057601083901c92506010810190505b6000600884901c111561399b57600883901c92506008810190505b6000600484901c11156139b657600483901c92506004810190505b6000600284901c11156139d157600283901c92506002810190505b6000600184901c11156139e5576001810190505b80915050919050565b60008183106139fd57816139ff565b825b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613a76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a6d90615959565b60405180910390fd5b613a8282600083612da2565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015613b08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613aff906159eb565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008282540392505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613bbb9190613ee4565b60405180910390a3613bcf83600084612dba565b505050565b60008083600052826020600020019050613bed81613c42565b91505092915050565b600080828054905003613c0c5760009050613c3d565b8160018380549050613c1e91906148a6565b81548110613c2f57613c2e6148da565b5b906000526020600020015490505b919050565b6000819050919050565b6040518060400160405280600063ffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681525090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613cc981613c94565b8114613cd457600080fd5b50565b600081359050613ce681613cc0565b92915050565b600060208284031215613d0257613d01613c8a565b5b6000613d1084828501613cd7565b91505092915050565b60008115159050919050565b613d2e81613d19565b82525050565b6000602082019050613d496000830184613d25565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613d89578082015181840152602081019050613d6e565b60008484015250505050565b6000601f19601f8301169050919050565b6000613db182613d4f565b613dbb8185613d5a565b9350613dcb818560208601613d6b565b613dd481613d95565b840191505092915050565b60006020820190508181036000830152613df98184613da6565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613e2c82613e01565b9050919050565b613e3c81613e21565b8114613e4757600080fd5b50565b600081359050613e5981613e33565b92915050565b6000819050919050565b613e7281613e5f565b8114613e7d57600080fd5b50565b600081359050613e8f81613e69565b92915050565b60008060408385031215613eac57613eab613c8a565b5b6000613eba85828601613e4a565b9250506020613ecb85828601613e80565b9150509250929050565b613ede81613e5f565b82525050565b6000602082019050613ef96000830184613ed5565b92915050565b600080600060608486031215613f1857613f17613c8a565b5b6000613f2686828701613e4a565b9350506020613f3786828701613e4a565b9250506040613f4886828701613e80565b9150509250925092565b6000819050919050565b613f6581613f52565b8114613f7057600080fd5b50565b600081359050613f8281613f5c565b92915050565b600060208284031215613f9e57613f9d613c8a565b5b6000613fac84828501613f73565b91505092915050565b613fbe81613f52565b82525050565b6000602082019050613fd96000830184613fb5565b92915050565b60008060408385031215613ff657613ff5613c8a565b5b600061400485828601613f73565b925050602061401585828601613e4a565b9150509250929050565b600060ff82169050919050565b6140358161401f565b82525050565b6000602082019050614050600083018461402c565b92915050565b60006020828403121561406c5761406b613c8a565b5b600061407a84828501613e80565b91505092915050565b60006020828403121561409957614098613c8a565b5b60006140a784828501613e4a565b91505092915050565b6140b981613e21565b82525050565b60006020820190506140d460008301846140b0565b92915050565b60006140e582613e21565b9050919050565b6140f5816140da565b811461410057600080fd5b50565b600081359050614112816140ec565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261413d5761413c614118565b5b8235905067ffffffffffffffff81111561415a5761415961411d565b5b60208301915083600182028301111561417657614175614122565b5b9250929050565b60008060008060006080868803121561419957614198613c8a565b5b60006141a788828901614103565b95505060206141b888828901613e4a565b94505060406141c988828901613e80565b935050606086013567ffffffffffffffff8111156141ea576141e9613c8f565b5b6141f688828901614127565b92509250509295509295909350565b600063ffffffff82169050919050565b61421e81614205565b82525050565b60006020820190506142396000830184614215565b92915050565b6142488161401f565b811461425357600080fd5b50565b6000813590506142658161423f565b92915050565b60008060008060008060c0878903121561428857614287613c8a565b5b600061429689828a01613e4a565b96505060206142a789828a01613e80565b95505060406142b889828a01613e80565b94505060606142c989828a01614256565b93505060806142da89828a01613f73565b92505060a06142eb89828a01613f73565b9150509295509295509295565b600080600080600080600060e0888a03121561431757614316613c8a565b5b60006143258a828b01613e4a565b97505060206143368a828b01613e4a565b96505060406143478a828b01613e80565b95505060606143588a828b01613e80565b94505060806143698a828b01614256565b93505060a061437a8a828b01613f73565b92505060c061438b8a828b01613f73565b91505092959891949750929550565b600080604083850312156143b1576143b0613c8a565b5b60006143bf85828601613e4a565b92505060206143d085828601613e4a565b9150509250929050565b6143e381614205565b81146143ee57600080fd5b50565b600081359050614400816143da565b92915050565b6000806040838503121561441d5761441c613c8a565b5b600061442b85828601613e4a565b925050602061443c858286016143f1565b9150509250929050565b61444f81614205565b82525050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b61448681614455565b82525050565b6040820160008201516144a26000850182614446565b5060208201516144b5602085018261447d565b50505050565b60006040820190506144d0600083018461448c565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061451d57607f821691505b6020821081036145305761452f6144d6565b5b50919050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b6000614592602f83613d5a565b915061459d82614536565b604082019050919050565b600060208201905081810360008301526145c181614585565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061460282613e5f565b915061460d83613e5f565b9250828201905080821115614625576146246145c8565b5b92915050565b7f4552433230566f7465733a20626c6f636b206e6f7420796574206d696e656400600082015250565b6000614661601f83613d5a565b915061466c8261462b565b602082019050919050565b6000602082019050818103600083015261469081614654565b9050919050565b7f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60008201527f6178466c6173684c6f616e000000000000000000000000000000000000000000602082015250565b60006146f3602b83613d5a565b91506146fe82614697565b604082019050919050565b60006020820190508181036000830152614722816146e6565b9050919050565b600082825260208201905092915050565b82818337600083830152505050565b60006147558385614729565b935061476283858461473a565b61476b83613d95565b840190509392505050565b600060a08201905061478b60008301896140b0565b61479860208301886140b0565b6147a56040830187613ed5565b6147b26060830186613ed5565b81810360808301526147c5818486614749565b9050979650505050505050565b6000815190506147e181613f5c565b92915050565b6000602082840312156147fd576147fc613c8a565b5b600061480b848285016147d2565b91505092915050565b7f4552433230466c6173684d696e743a20696e76616c69642072657475726e207660008201527f616c756500000000000000000000000000000000000000000000000000000000602082015250565b6000614870602483613d5a565b915061487b82614814565b604082019050919050565b6000602082019050818103600083015261489f81614863565b9050919050565b60006148b182613e5f565b91506148bc83613e5f565b92508282039050818111156148d4576148d36145c8565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000614965602583613d5a565b915061497082614909565b604082019050919050565b6000602082019050818103600083015261499481614958565b9050919050565b7f4552433230566f7465733a207369676e61747572652065787069726564000000600082015250565b60006149d1601d83613d5a565b91506149dc8261499b565b602082019050919050565b60006020820190508181036000830152614a00816149c4565b9050919050565b6000608082019050614a1c6000830187613fb5565b614a2960208301866140b0565b614a366040830185613ed5565b614a436060830184613ed5565b95945050505050565b7f4552433230566f7465733a20696e76616c6964206e6f6e636500000000000000600082015250565b6000614a82601983613d5a565b9150614a8d82614a4c565b602082019050919050565b60006020820190508181036000830152614ab181614a75565b9050919050565b7f45524332305065726d69743a206578706972656420646561646c696e65000000600082015250565b6000614aee601d83613d5a565b9150614af982614ab8565b602082019050919050565b60006020820190508181036000830152614b1d81614ae1565b9050919050565b600060c082019050614b396000830189613fb5565b614b4660208301886140b0565b614b5360408301876140b0565b614b606060830186613ed5565b614b6d6080830185613ed5565b614b7a60a0830184613ed5565b979650505050505050565b7f45524332305065726d69743a20696e76616c6964207369676e61747572650000600082015250565b6000614bbb601e83613d5a565b9150614bc682614b85565b602082019050919050565b60006020820190508181036000830152614bea81614bae565b9050919050565b7f4552433230466c6173684d696e743a2077726f6e6720746f6b656e0000000000600082015250565b6000614c27601b83613d5a565b9150614c3282614bf1565b602082019050919050565b60006020820190508181036000830152614c5681614c1a565b9050919050565b7f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60008201527f766572666c6f77696e6720766f74657300000000000000000000000000000000602082015250565b6000614cb9603083613d5a565b9150614cc482614c5d565b604082019050919050565b60006020820190508181036000830152614ce881614cac565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b6000614d25601f83613d5a565b9150614d3082614cef565b602082019050919050565b60006020820190508181036000830152614d5481614d18565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203260008201527f3234206269747300000000000000000000000000000000000000000000000000602082015250565b6000614db7602783613d5a565b9150614dc282614d5b565b604082019050919050565b60006020820190508181036000830152614de681614daa565b9050919050565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203360008201527f3220626974730000000000000000000000000000000000000000000000000000602082015250565b6000614e49602683613d5a565b9150614e5482614ded565b604082019050919050565b60006020820190508181036000830152614e7881614e3c565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000614edb602483613d5a565b9150614ee682614e7f565b604082019050919050565b60006020820190508181036000830152614f0a81614ece565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b6000614f6d602283613d5a565b9150614f7882614f11565b604082019050919050565b60006020820190508181036000830152614f9c81614f60565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b6000614fd9601d83613d5a565b9150614fe482614fa3565b602082019050919050565b6000602082019050818103600083015261500881614fcc565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b600061506b602583613d5a565b91506150768261500f565b604082019050919050565b6000602082019050818103600083015261509a8161505e565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b60006150fd602383613d5a565b9150615108826150a1565b604082019050919050565b6000602082019050818103600083015261512c816150f0565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b600061518f602683613d5a565b915061519a82615133565b604082019050919050565b600060208201905081810360008301526151be81615182565b9050919050565b7f4552433230536e617073686f743a206964206973203000000000000000000000600082015250565b60006151fb601683613d5a565b9150615206826151c5565b602082019050919050565b6000602082019050818103600083015261522a816151ee565b9050919050565b7f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000600082015250565b6000615267601d83613d5a565b915061527282615231565b602082019050919050565b600060208201905081810360008301526152968161525a565b9050919050565b60006040820190506152b26000830185613ed5565b6152bf6020830184613ed5565b9392505050565b600081905092915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006153076017836152c6565b9150615312826152d1565b601782019050919050565b600061532882613d4f565b61533281856152c6565b9350615342818560208601613d6b565b80840191505092915050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b60006153846011836152c6565b915061538f8261534e565b601182019050919050565b60006153a5826152fa565b91506153b1828561531d565b91506153bc82615377565b91506153c8828461531d565b91508190509392505050565b600060a0820190506153e96000830188613fb5565b6153f66020830187613fb5565b6154036040830186613fb5565b6154106060830185613ed5565b61541d60808301846140b0565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061546182613e5f565b915061546c83613e5f565b92508261547c5761547b615427565b5b828204905092915050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006154bd601483613d5a565b91506154c882615487565b602082019050919050565b600060208201905081810360008301526154ec816154b0565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000615529601083613d5a565b9150615534826154f3565b602082019050919050565b600060208201905081810360008301526155588161551c565b9050919050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b60006155956002836152c6565b91506155a08261555f565b600282019050919050565b6000819050919050565b6155c66155c182613f52565b6155ab565b82525050565b60006155d782615588565b91506155e382856155b5565b6020820191506155f382846155b5565b6020820191508190509392505050565b60006080820190506156186000830187613fb5565b615625602083018661402c565b6156326040830185613fb5565b61563f6060830184613fb5565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b60006156ad601883613d5a565b91506156b882615677565b602082019050919050565b600060208201905081810360008301526156dc816156a0565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615719601f83613d5a565b9150615724826156e3565b602082019050919050565b600060208201905081810360008301526157488161570c565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b60006157ab602283613d5a565b91506157b68261574f565b604082019050919050565b600060208201905081810360008301526157da8161579e565b9050919050565b60006157ec82613e5f565b91506157f783613e5f565b925082820261580581613e5f565b9150828204841483151761581c5761581b6145c8565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061585d82613e5f565b9150600082036158705761586f6145c8565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006158b1602083613d5a565b91506158bc8261587b565b602082019050919050565b600060208201905081810360008301526158e0816158a4565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b6000615943602183613d5a565b915061594e826158e7565b604082019050919050565b6000602082019050818103600083015261597281615936565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b60006159d5602283613d5a565b91506159e082615979565b604082019050919050565b60006020820190508181036000830152615a04816159c8565b905091905056fea2646970667358221220c004ab49ae258f385157b7351af018d745305cd9613cbe87b316ed098632674a64736f6c63430008120033

Deployed Bytecode Sourcemap

141872:1845:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90647:204;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;102092:100;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104443:201;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103212:108;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105224:295;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92470:131;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92911:147;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;103054:93;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120919:115;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94055:218;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;105928:238;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124127:268;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142706:77;;;:::i;:::-;;142791:107;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;141210:91;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;136726:266;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123501:128;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;127013:114;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;87082:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117128:959;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;114214:178;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123257:151;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;141998:66;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103383:127;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;141620:164;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;120661:128;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142625:73;;;:::i;:::-;;124684:259;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;90943:147;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;102311:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142536:81;;;:::i;:::-;;137096:234;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123713:212;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;90048:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;106669:436;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103716:193;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;127209:591;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119950:645;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;142140:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93351:149;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;114768:219;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103972:151;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142071:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123027:150;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;90647:204;90732:4;90771:32;90756:47;;;:11;:47;;;;:87;;;;90807:36;90831:11;90807:23;:36::i;:::-;90756:87;90749:94;;90647:204;;;:::o;102092:100::-;102146:13;102179:5;102172:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102092:100;:::o;104443:201::-;104526:4;104543:13;104559:12;:10;:12::i;:::-;104543:28;;104582:32;104591:5;104598:7;104607:6;104582:8;:32::i;:::-;104632:4;104625:11;;;104443:201;;;;:::o;103212:108::-;103273:7;103300:12;;103293:19;;103212:108;:::o;105224:295::-;105355:4;105372:15;105390:12;:10;:12::i;:::-;105372:30;;105413:38;105429:4;105435:7;105444:6;105413:15;:38::i;:::-;105462:27;105472:4;105478:2;105482:6;105462:9;:27::i;:::-;105507:4;105500:11;;;105224:295;;;;;:::o;92470:131::-;92544:7;92571:6;:12;92578:4;92571:12;;;;;;;;;;;:22;;;92564:29;;92470:131;;;:::o;92911:147::-;92994:18;93007:4;92994:12;:18::i;:::-;90539:16;90550:4;90539:10;:16::i;:::-;93025:25:::1;93036:4;93042:7;93025:10;:25::i;:::-;92911:147:::0;;;:::o;103054:93::-;103112:5;103137:2;103130:9;;103054:93;:::o;120919:115::-;120979:7;121006:20;:18;:20::i;:::-;120999:27;;120919:115;:::o;94055:218::-;94162:12;:10;:12::i;:::-;94151:23;;:7;:23;;;94143:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;94239:26;94251:4;94257:7;94239:11;:26::i;:::-;94055:218;;:::o;105928:238::-;106016:4;106033:13;106049:12;:10;:12::i;:::-;106033:28;;106072:64;106081:5;106088:7;106125:10;106097:25;106107:5;106114:7;106097:9;:25::i;:::-;:38;;;;:::i;:::-;106072:8;:64::i;:::-;106154:4;106147:11;;;105928:238;;;;:::o;124127:268::-;124225:7;124267:12;124253:11;:26;124245:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;124333:54;124352:12;:21;124365:7;124352:21;;;;;;;;;;;;;;;124375:11;124333:18;:54::i;:::-;124326:61;;124127:268;;;;:::o;142706:77::-;142109:24;90539:16;90550:4;90539:10;:16::i;:::-;142765:10:::1;:8;:10::i;:::-;142706:77:::0;:::o;142791:107::-;142178:24;90539:16;90550:4;90539:10;:16::i;:::-;142873:17:::1;142879:2;142883:6;142873:5;:17::i;:::-;142791:107:::0;;;:::o;141210:91::-;141266:27;141272:12;:10;:12::i;:::-;141286:6;141266:5;:27::i;:::-;141210:91;:::o;136726:266::-;136813:7;136834:16;136852:13;136869:55;136878:10;136890:24;:33;136915:7;136890:33;;;;;;;;;;;;;;;136869:8;:55::i;:::-;136833:91;;;;136944:11;:40;;136966:18;136976:7;136966:9;:18::i;:::-;136944:40;;;136958:5;136944:40;136937:47;;;;136726:266;;;;:::o;123501:128::-;123575:7;123602:10;:19;123613:7;123602:19;;;;;;;;;;;;;;;;;;;;;;;;;123595:26;;123501:128;;;:::o;127013:114::-;127085:34;127095:12;:10;:12::i;:::-;127109:9;127085;:34::i;:::-;127013:114;:::o;87082:86::-;87129:4;87153:7;;;;;;;;;;;87146:14;;87082:86;:::o;117128:959::-;117307:4;117342:19;117355:5;117342:12;:19::i;:::-;117332:6;:29;;117324:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;117420:11;117434:23;117443:5;117450:6;117434:8;:23::i;:::-;117420:37;;117468:32;117482:8;117493:6;117468:5;:32::i;:::-;113951:45;117533:8;:20;;;117554:10;117566:5;117573:6;117581:3;117586:4;;117533:58;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:75;117511:161;;;;;;;;;;;;:::i;:::-;;;;;;;;;117683:24;117710:19;:17;:19::i;:::-;117683:46;;117740:63;117764:8;117783:4;117799:3;117790:6;:12;;;;:::i;:::-;117740:15;:63::i;:::-;117825:1;117818:3;:8;:42;;;;117858:1;117830:30;;:16;:30;;;117818:42;117814:244;;;117877:38;117891:8;117911:3;117902:6;:12;;;;:::i;:::-;117877:5;:38::i;:::-;117814:244;;;117948:32;117962:8;117973:6;117948:5;:32::i;:::-;117995:51;118013:8;118024:16;118042:3;117995:9;:51::i;:::-;117814:244;118075:4;118068:11;;;;117128:959;;;;;;;:::o;114214:178::-;114289:7;114333:4;114316:22;;:5;:22;;;:68;;114383:1;114316:68;;;114361:19;:17;:19::i;:::-;114341:17;:39;;;;:::i;:::-;114316:68;114309:75;;114214:178;;;:::o;123257:151::-;123327:6;123353:47;123371:12;:21;123384:7;123371:21;;;;;;;;;;;;;;;:28;;;;123353:17;:47::i;:::-;123346:54;;123257:151;;;:::o;141998:66::-;142038:26;141998:66;:::o;103383:127::-;103457:7;103484:9;:18;103494:7;103484:18;;;;;;;;;;;;;;;;103477:25;;103383:127;;;:::o;141620:164::-;141697:46;141713:7;141722:12;:10;:12::i;:::-;141736:6;141697:15;:46::i;:::-;141754:22;141760:7;141769:6;141754:5;:22::i;:::-;141620:164;;:::o;120661:128::-;120730:7;120757:24;:7;:14;120765:5;120757:14;;;;;;;;;;;;;;;:22;:24::i;:::-;120750:31;;120661:128;;;:::o;142625:73::-;142109:24;90539:16;90550:4;90539:10;:16::i;:::-;142682:8:::1;:6;:8::i;:::-;142625:73:::0;:::o;124684:259::-;124771:7;124813:12;124799:11;:26;124791:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;124879:56;124898:23;124923:11;124879:18;:56::i;:::-;124872:63;;124684:259;;;:::o;90943:147::-;91029:4;91053:6;:12;91060:4;91053:12;;;;;;;;;;;:20;;:29;91074:7;91053:29;;;;;;;;;;;;;;;;;;;;;;;;;91046:36;;90943:147;;;;:::o;102311:104::-;102367:13;102400:7;102393:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102311:104;:::o;142536:81::-;142038:26;90539:16;90550:4;90539:10;:16::i;:::-;142598:11:::1;:9;:11::i;:::-;;142536:81:::0;:::o;137096:234::-;137168:7;137189:16;137207:13;137224:43;137233:10;137245:21;137224:8;:43::i;:::-;137188:79;;;;137287:11;:35;;137309:13;:11;:13::i;:::-;137287:35;;;137301:5;137287:35;137280:42;;;;137096:234;;;:::o;123713:212::-;123786:7;123806:11;123820:12;:21;123833:7;123820:21;;;;;;;;;;;;;;;:28;;;;123806:42;;123873:1;123866:3;:8;:51;;123881:12;:21;123894:7;123881:21;;;;;;;;;;;;;;;123909:1;123903:3;:7;;;;:::i;:::-;123881:30;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;;;;;;;;;123866:51;;;123877:1;123866:51;123859:58;;;;;123713:212;;;:::o;90048:49::-;90093:4;90048:49;;;:::o;106669:436::-;106762:4;106779:13;106795:12;:10;:12::i;:::-;106779:28;;106818:24;106845:25;106855:5;106862:7;106845:9;:25::i;:::-;106818:52;;106909:15;106889:16;:35;;106881:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;107002:60;107011:5;107018:7;107046:15;107027:16;:34;107002:8;:60::i;:::-;107093:4;107086:11;;;;106669:436;;;;:::o;103716:193::-;103795:4;103812:13;103828:12;:10;:12::i;:::-;103812:28;;103851;103861:5;103868:2;103872:6;103851:9;:28::i;:::-;103897:4;103890:11;;;103716:193;;;;:::o;127209:591::-;127436:6;127417:15;:25;;127409:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;127487:14;127504:174;127532:87;122707:71;127592:9;127603:5;127610:6;127559:58;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;127549:69;;;;;;127532:16;:87::i;:::-;127634:1;127650;127666;127504:13;:174::i;:::-;127487:191;;127706:17;127716:6;127706:9;:17::i;:::-;127697:5;:26;127689:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;127764:28;127774:6;127782:9;127764;:28::i;:::-;127398:402;127209:591;;;;;;:::o;119950:645::-;120194:8;120175:15;:27;;120167:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;120249:18;119125:95;120309:5;120316:7;120325:5;120332:16;120342:5;120332:9;:16::i;:::-;120350:8;120280:79;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;120270:90;;;;;;120249:111;;120373:12;120388:28;120405:10;120388:16;:28::i;:::-;120373:43;;120429:14;120446:28;120460:4;120466:1;120469;120472;120446:13;:28::i;:::-;120429:45;;120503:5;120493:15;;:6;:15;;;120485:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;120556:31;120565:5;120572:7;120581:5;120556:8;:31::i;:::-;120156:439;;;119950:645;;;;;;;:::o;142140:62::-;142178:24;142140:62;:::o;93351:149::-;93435:18;93448:4;93435:12;:18::i;:::-;90539:16;90550:4;90539:10;:16::i;:::-;93466:26:::1;93478:4;93484:7;93466:11;:26::i;:::-;93351:149:::0;;;:::o;114768:219::-;114855:7;114900:4;114883:22;;:5;:22;;;114875:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;114955:24;114965:5;114972:6;114955:9;:24::i;:::-;114948:31;;114768:219;;;;:::o;103972:151::-;104061:7;104088:11;:18;104100:5;104088:18;;;;;;;;;;;;;;;:27;104107:7;104088:27;;;;;;;;;;;;;;;;104081:34;;103972:151;;;;:::o;142071:62::-;142109:24;142071:62;:::o;123027:150::-;123106:17;;:::i;:::-;123143:12;:21;123156:7;123143:21;;;;;;;;;;;;;;;123165:3;123143:26;;;;;;;;;;:::i;:::-;;;;;;;;;123136:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123027:150;;;;:::o;128106:290::-;128191:28;128203:7;128212:6;128191:11;:28::i;:::-;128255:12;:10;:12::i;:::-;128238:29;;:13;:11;:13::i;:::-;:29;;128230:90;;;;;;;;;;;;:::i;:::-;;;;;;;;;128333:55;128350:23;128375:4;128381:6;128333:16;:55::i;:::-;;;128106:290;;:::o;108702:548::-;108805:1;108786:21;;:7;:21;;;108778:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;108856:49;108885:1;108889:7;108898:6;108856:20;:49::i;:::-;108934:6;108918:12;;:22;;;;;;;:::i;:::-;;;;;;;;109111:6;109089:9;:18;109099:7;109089:18;;;;;;;;;;;;;;;;:28;;;;;;;;;;;109165:7;109144:37;;109161:1;109144:37;;;109174:6;109144:37;;;;;;:::i;:::-;;;;;;;;109194:48;109222:1;109226:7;109235:6;109194:19;:48::i;:::-;108702:548;;:::o;131059:98::-;131117:7;131148:1;131144;:5;;;;:::i;:::-;131137:12;;131059:98;;;;:::o;5453:195::-;5510:7;5547:17;5538:26;;:5;:26;;5530:78;;;;;;;;;;;;:::i;:::-;;;;;;;;;5634:5;5619:21;;5453:195;;;:::o;18289:190::-;18345:6;18381:16;18372:25;;:5;:25;;18364:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;18465:5;18451:20;;18289:190;;;:::o;137547:622::-;137690:44;137717:4;137723:2;137727:6;137690:26;:44::i;:::-;137767:1;137751:18;;:4;:18;;;137747:415;;137807:26;137830:2;137807:22;:26::i;:::-;137848:28;:26;:28::i;:::-;137747:415;;;137912:1;137898:16;;:2;:16;;;137894:268;;137952:28;137975:4;137952:22;:28::i;:::-;137995;:26;:28::i;:::-;137894:268;;;138081:28;138104:4;138081:22;:28::i;:::-;138124:26;138147:2;138124:22;:26::i;:::-;137894:268;137747:415;137547:622;;;:::o;128831:262::-;128973:43;128999:4;129005:2;129009:6;128973:25;:43::i;:::-;129029:56;129046:15;129056:4;129046:9;:15::i;:::-;129063:13;129073:2;129063:9;:13::i;:::-;129078:6;129029:16;:56::i;:::-;128831:262;;;:::o;112420:125::-;;;;:::o;113149:124::-;;;;:::o;131165:103::-;131228:7;131259:1;131255;:5;;;;:::i;:::-;131248:12;;131165:103;;;;:::o;49171:114::-;49236:7;49263;:14;;;49256:21;;49171:114;;;:::o;45082:157::-;45167:4;45206:25;45191:40;;;:11;:40;;;;45184:47;;45082:157;;;:::o;85189:98::-;85242:7;85269:10;85262:17;;85189:98;:::o;110696:380::-;110849:1;110832:19;;:5;:19;;;110824:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;110930:1;110911:21;;:7;:21;;;110903:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;111014:6;110984:11;:18;110996:5;110984:18;;;;;;;;;;;;;;;:27;111003:7;110984:27;;;;;;;;;;;;;;;:36;;;;111052:7;111036:32;;111045:5;111036:32;;;111061:6;111036:32;;;;;;:::i;:::-;;;;;;;;110696:380;;;:::o;111367:453::-;111502:24;111529:25;111539:5;111546:7;111529:9;:25::i;:::-;111502:52;;111589:17;111569:16;:37;111565:248;;111651:6;111631:16;:26;;111623:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;111735:51;111744:5;111751:7;111779:6;111760:16;:25;111735:8;:51::i;:::-;111565:248;111491:329;111367:453;;;:::o;107575:840::-;107722:1;107706:18;;:4;:18;;;107698:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;107799:1;107785:16;;:2;:16;;;107777:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;107854:38;107875:4;107881:2;107885:6;107854:20;:38::i;:::-;107905:19;107927:9;:15;107937:4;107927:15;;;;;;;;;;;;;;;;107905:37;;107976:6;107961:11;:21;;107953:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;108093:6;108079:11;:20;108061:9;:15;108071:4;108061:15;;;;;;;;;;;;;;;:38;;;;108296:6;108279:9;:13;108289:2;108279:13;;;;;;;;;;;;;;;;:23;;;;;;;;;;;108346:2;108331:26;;108340:4;108331:26;;;108350:6;108331:26;;;;;;:::i;:::-;;;;;;;;108370:37;108390:4;108396:2;108400:6;108370:19;:37::i;:::-;107687:728;107575:840;;;:::o;91394:105::-;91461:30;91472:4;91478:12;:10;:12::i;:::-;91461:10;:30::i;:::-;91394:105;:::o;95652:238::-;95736:22;95744:4;95750:7;95736;:22::i;:::-;95731:152;;95807:4;95775:6;:12;95782:4;95775:12;;;;;;;;;;;:20;;:29;95796:7;95775:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;95858:12;:10;:12::i;:::-;95831:40;;95849:7;95831:40;;95843:4;95831:40;;;;;;;;;;95731:152;95652:238;;:::o;76981:314::-;77034:7;77075:12;77058:29;;77066:4;77058:29;;;:66;;;;;77108:16;77091:13;:33;77058:66;77054:234;;;77148:24;77141:31;;;;77054:234;77212:64;77234:10;77246:12;77260:15;77212:21;:64::i;:::-;77205:71;;76981:314;;:::o;96070:239::-;96154:22;96162:4;96168:7;96154;:22::i;:::-;96150:152;;;96225:5;96193:6;:12;96200:4;96193:12;;;;;;;;;;;:20;;:29;96214:7;96193:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;96277:12;:10;:12::i;:::-;96250:40;;96268:7;96250:40;;96262:4;96250:40;;;;;;;;;;96150:152;96070:239;;:::o;125032:1895::-;125131:7;126232:14;126249:5;:12;;;;126232:29;;126274:11;126300:12;126315:6;126300:21;;126347:1;126338:6;:10;126334:251;;;126365:11;126388:17;126398:6;126388:9;:17::i;:::-;126379:6;:26;;;;:::i;:::-;126365:40;;126462:11;126424:25;126438:5;126445:3;126424:13;:25::i;:::-;:35;;;;;;;;;;;;:49;;;126420:154;;;126501:3;126494:10;;126420:154;;;126557:1;126551:3;:7;;;;:::i;:::-;126545:13;;126420:154;126350:235;126334:251;126597;126610:4;126604:3;:10;126597:251;;;126631:11;126645:23;126658:3;126663:4;126645:12;:23::i;:::-;126631:37;;126725:11;126687:25;126701:5;126708:3;126687:13;:25::i;:::-;:35;;;;;;;;;;;;:49;;;126683:154;;;126764:3;126757:10;;126683:154;;;126820:1;126814:3;:7;;;;:::i;:::-;126808:13;;126683:154;126616:232;126597:251;;;126875:1;126867:4;:9;:52;;126883:30;126897:5;126911:1;126904:4;:8;;;;:::i;:::-;126883:13;:30::i;:::-;:36;;;;;;;;;;;;126867:52;;;126879:1;126867:52;126860:59;;;;;;;125032:1895;;;;:::o;87937:120::-;86946:16;:14;:16::i;:::-;88006:5:::1;87996:7;;:15;;;;;;;;;;;;;;;;;;88027:22;88036:12;:10;:12::i;:::-;88027:22;;;;;;:::i;:::-;;;;;;;;87937:120::o:0;143406:145::-;143520:23;143532:2;143536:6;143520:11;:23::i;:::-;143406:145;;:::o;143559:155::-;143678:28;143690:7;143699:6;143678:11;:28::i;:::-;143559:155;;:::o;138177:1619::-;138266:4;138272:7;138313:1;138300:10;:14;138292:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;138374:23;:21;:23::i;:::-;138360:10;:37;;138352:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;139570:13;139586:40;139615:10;139586:9;:13;;:28;;:40;;;;:::i;:::-;139570:56;;139652:9;:13;;:20;;;;139643:5;:29;139639:150;;139697:5;139704:1;139689:17;;;;;;;139639:150;139747:4;139753:9;:16;;139770:5;139753:23;;;;;;;;:::i;:::-;;;;;;;;;;139739:38;;;;;138177:1619;;;;;;:::o;129271:388::-;129356:23;129382:20;129392:9;129382;:20::i;:::-;129356:46;;129413:24;129440:20;129450:9;129440;:20::i;:::-;129413:47;;129495:9;129471:10;:21;129482:9;129471:21;;;;;;;;;;;;;;;;:33;;;;;;;;;;;;;;;;;;129566:9;129522:54;;129549:15;129522:54;;129538:9;129522:54;;;;;;;;;;;;129589:62;129606:15;129623:9;129634:16;129589;:62::i;:::-;129345:314;;129271:388;;:::o;115947:105::-;116007:7;115947:105;:::o;87678:118::-;86687:19;:17;:19::i;:::-;87748:4:::1;87738:7;;:14;;;;;;;;;;;;;;;;;;87768:20;87775:12;:10;:12::i;:::-;87768:20;;;;;;:::i;:::-;;;;;;;;87678:118::o:0;136198:223::-;136245:7;136265:30;:18;:28;:30::i;:::-;136308:17;136328:23;:21;:23::i;:::-;136308:43;;136367:19;136376:9;136367:19;;;;;;:::i;:::-;;;;;;;;136404:9;136397:16;;;136198:223;:::o;78208:167::-;78285:7;78312:55;78334:20;:18;:20::i;:::-;78356:10;78312:21;:55::i;:::-;78305:62;;78208:167;;;:::o;71848:279::-;71976:7;71997:17;72016:18;72038:25;72049:4;72055:1;72058;72061;72038:10;:25::i;:::-;71996:67;;;;72074:18;72086:5;72074:11;:18::i;:::-;72110:9;72103:16;;;;71848:279;;;;;;:::o;121172:207::-;121232:15;121260:30;121293:7;:14;121301:5;121293:14;;;;;;;;;;;;;;;121260:47;;121328:15;:5;:13;:15::i;:::-;121318:25;;121354:17;:5;:15;:17::i;:::-;121249:130;121172:207;;;:::o;115386:234::-;115467:7;115386:234;;;;:::o;127907:105::-;127960:7;127987:17;127980:24;;127907:105;:::o;130318:733::-;130492:17;130511;130541:11;130555:5;:12;;;;130541:26;;130580:25;130615:1;130608:3;:8;:59;;130638:29;130652:5;130665:1;130659:3;:7;;;;:::i;:::-;130638:13;:29::i;:::-;130608:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130619:16;;;;;;;;130630:1;130619:16;;;;;;130633:1;130619:16;;;;;130608:59;130580:87;;130692:7;:13;;;130680:25;;;;130728:20;130731:9;130742:5;130728:2;:20;;:::i;:::-;130716:32;;130771:1;130765:3;:7;:44;;;;;130797:12;130776:7;:17;;;:33;;;130765:44;130761:283;;;130864:29;130883:9;130864:18;:29::i;:::-;130826;130840:5;130853:1;130847:3;:7;;;;:::i;:::-;130826:13;:29::i;:::-;:35;;;:67;;;;;;;;;;;;;;;;;;130761:283;;;130926:5;130937:94;;;;;;;;130960:31;130978:12;130960:17;:31::i;:::-;130937:94;;;;;;131000:29;131019:9;131000:18;:29::i;:::-;130937:94;;;;;130926:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130761:283;130530:521;;130318:733;;;;;;:::o;142906:221::-;86687:19;:17;:19::i;:::-;143075:44:::1;143102:4;143108:2;143112:6;143075:26;:44::i;:::-;142906:221:::0;;;:::o;143205:193::-;143347:43;143373:4;143379:2;143383:6;143347:25;:43::i;:::-;143205:193;;;:::o;139804:146::-;139872:70;139888:24;:33;139913:7;139888:33;;;;;;;;;;;;;;;139923:18;139933:7;139923:9;:18::i;:::-;139872:15;:70::i;:::-;139804:146;:::o;139958:118::-;140015:53;140031:21;140054:13;:11;:13::i;:::-;140015:15;:53::i;:::-;139958:118::o;129667:643::-;129799:3;129792:10;;:3;:10;;;;:24;;;;;129815:1;129806:6;:10;129792:24;129788:515;;;129852:1;129837:17;;:3;:17;;;129833:224;;129876:17;129895;129916:54;129933:12;:17;129946:3;129933:17;;;;;;;;;;;;;;;129952:9;129963:6;129916:16;:54::i;:::-;129875:95;;;;130015:3;129994:47;;;130020:9;130031;129994:47;;;;;;;:::i;:::-;;;;;;;;129856:201;;129833:224;130092:1;130077:17;;:3;:17;;;130073:219;;130116:17;130135;130156:49;130173:12;:17;130186:3;130173:17;;;;;;;;;;;;;;;130192:4;130198:6;130156:16;:49::i;:::-;130115:90;;;;130250:3;130229:47;;;130255:9;130266;130229:47;;;;;;;:::i;:::-;;;;;;;;130096:196;;130073:219;129788:515;129667:643;;;:::o;91789:492::-;91878:22;91886:4;91892:7;91878;:22::i;:::-;91873:401;;92066:28;92086:7;92066:19;:28::i;:::-;92167:38;92195:4;92187:13;;92202:2;92167:19;:38::i;:::-;91971:257;;;;;;;;;:::i;:::-;;;;;;;;;;;;;91917:345;;;;;;;;;;;:::i;:::-;;;;;;;;91873:401;91789:492;;:::o;77303:263::-;77447:7;77495:8;77505;77515:11;77528:13;77551:4;77484:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;77474:84;;;;;;77467:91;;77303:263;;;;;:::o;56232:1673::-;56280:7;56309:1;56304;:6;56300:47;;56334:1;56327:8;;;;56300:47;57038:14;57072:1;57061:7;57066:1;57061:4;:7::i;:::-;:12;;57055:1;:19;;57038:36;;57540:1;57529:6;57525:1;:10;;;;;:::i;:::-;;;57516:6;:19;57515:26;;57506:35;;57590:1;57579:6;57575:1;:10;;;;;:::i;:::-;;;57566:6;:19;57565:26;;57556:35;;57640:1;57629:6;57625:1;:10;;;;;:::i;:::-;;;57616:6;:19;57615:26;;57606:35;;57690:1;57679:6;57675:1;:10;;;;;:::i;:::-;;;57666:6;:19;57665:26;;57656:35;;57740:1;57729:6;57725:1;:10;;;;;:::i;:::-;;;57716:6;:19;57715:26;;57706:35;;57790:1;57779:6;57775:1;:10;;;;;:::i;:::-;;;57766:6;:19;57765:26;;57756:35;;57840:1;57829:6;57825:1;:10;;;;;:::i;:::-;;;57816:6;:19;57815:26;;57806:35;;57863:23;57867:6;57879;57875:1;:10;;;;;:::i;:::-;;;57863:3;:23::i;:::-;57856:30;;;56232:1673;;;;:::o;131416:244::-;131502:25;131574:10;131571:1;131564:21;131638:3;131631:4;131628:1;131618:18;131614:28;131599:43;;131416:244;;;;:::o;50633:156::-;50695:7;50780:1;50775;50771;:5;50770:11;;;;:::i;:::-;50765:1;50761;:5;50760:21;;;;:::i;:::-;50753:28;;50633:156;;;;:::o;87426:108::-;87493:8;:6;:8::i;:::-;87485:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;87426:108::o;128490:194::-;128575:28;128587:7;128596:6;128575:11;:28::i;:::-;128616:60;128633:23;128658:9;128669:6;128616:16;:60::i;:::-;;;128490:194;;:::o;136487:127::-;136551:7;136578:28;:18;:26;:28::i;:::-;136571:35;;136487:127;:::o;81886:958::-;81975:7;82015:1;81999:5;:12;;;;:17;81995:58;;82040:1;82033:8;;;;81995:58;82065:11;82091:12;82106:5;:12;;;;82091:27;;82131:444;82144:4;82138:3;:10;82131:444;;;82165:11;82179:23;82192:3;82197:4;82179:12;:23::i;:::-;82165:37;;82456:7;82423:24;82436:5;82443:3;82423:12;:24::i;:::-;:30;;;:40;82419:145;;;82491:3;82484:10;;82419:145;;;82547:1;82541:3;:7;;;;:::i;:::-;82535:13;;82419:145;82150:425;82131:444;;;82701:1;82695:3;:7;:56;;;;;82744:7;82706:28;82719:5;82732:1;82726:3;:7;;;;:::i;:::-;82706:12;:28::i;:::-;:34;;;:45;82695:56;82691:146;;;82781:1;82775:3;:7;;;;:::i;:::-;82768:14;;;;;;82691:146;82822:3;82815:10;;;;81886:958;;;;;:::o;87241:108::-;87312:8;:6;:8::i;:::-;87311:9;87303:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;87241:108::o;49293:127::-;49400:1;49382:7;:14;;;:19;;;;;;;;;;;49293:127;:::o;73539:196::-;73632:7;73698:15;73715:10;73669:57;;;;;;;;;:::i;:::-;;;;;;;;;;;;;73659:68;;;;;;73652:75;;73539:196;;;;:::o;70189:1520::-;70320:7;70329:12;71254:66;71249:1;71241:10;;:79;71237:163;;;71353:1;71357:30;71337:51;;;;;;71237:163;71497:14;71514:24;71524:4;71530:1;71533;71536;71514:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71497:41;;71571:1;71553:20;;:6;:20;;;71549:103;;71606:1;71610:29;71590:50;;;;;;;71549:103;71672:6;71680:20;71664:37;;;;;70189:1520;;;;;;;;:::o;65581:521::-;65659:20;65650:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;65646:449;65696:7;65646:449;65757:29;65748:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;65744:351;;65803:34;;;;;;;;;;:::i;:::-;;;;;;;;65744:351;65868:35;65859:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;65855:240;;65920:41;;;;;;;;;;:::i;:::-;;;;;;;;65855:240;65992:30;65983:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;65979:116;;66039:44;;;;;;;;;;:::i;:::-;;;;;;;;65979:116;65581:521;;:::o;140084:310::-;140179:17;140199:23;:21;:23::i;:::-;140179:43;;140270:9;140237:30;140253:9;:13;;140237:15;:30::i;:::-;:42;140233:154;;;140296:9;:13;;140315:9;140296:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;140340:9;:16;;140362:12;140340:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;140233:154;140168:226;140084:310;;:::o;64817:151::-;64875:13;64908:52;64936:4;64920:22;;62972:2;64908:52;;:11;:52::i;:::-;64901:59;;64817:151;;;:::o;64213:447::-;64288:13;64314:19;64359:1;64350:6;64346:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;64336:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64314:47;;64372:15;:6;64379:1;64372:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;64398;:6;64405:1;64398:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;64429:9;64454:1;64445:6;64441:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;64429:26;;64424:131;64461:1;64457;:5;64424:131;;;64496:8;64513:3;64505:5;:11;64496:21;;;;;;;:::i;:::-;;;;;64484:6;64491:1;64484:9;;;;;;;;:::i;:::-;;;;;:33;;;;;;;;;;;64542:1;64532:11;;;;;64464:3;;;;:::i;:::-;;;64424:131;;;;64582:1;64573:5;:10;64565:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;64645:6;64631:21;;;64213:447;;;;:::o;58382:1019::-;58434:7;58454:14;58471:1;58454:18;;58527:1;58521:3;58512:5;:12;;:16;58508:102;;;58559:3;58549:13;;;;;58591:3;58581:13;;;;58508:102;58642:1;58637:2;58628:5;:11;;:15;58624:99;;;58674:2;58664:12;;;;;58705:2;58695:12;;;;58624:99;58755:1;58750:2;58741:5;:11;;:15;58737:99;;;58787:2;58777:12;;;;;58818:2;58808:12;;;;58737:99;58868:1;58863:2;58854:5;:11;;:15;58850:99;;;58900:2;58890:12;;;;;58931:2;58921:12;;;;58850:99;58980:1;58976;58967:5;:10;;:14;58963:96;;;59012:1;59002:11;;;;;59042:1;59032:11;;;;58963:96;59090:1;59086;59077:5;:10;;:14;59073:96;;;59122:1;59112:11;;;;;59152:1;59142:11;;;;59073:96;59200:1;59196;59187:5;:10;;:14;59183:96;;;59232:1;59222:11;;;;;59262:1;59252:11;;;;59183:96;59310:1;59306;59297:5;:10;;:14;59293:66;;;59342:1;59332:11;;;;59293:66;59387:6;59380:13;;;58382:1019;;;:::o;50408:106::-;50466:7;50497:1;50493;:5;:13;;50505:1;50493:13;;;50501:1;50493:13;50486:20;;50408:106;;;;:::o;109583:675::-;109686:1;109667:21;;:7;:21;;;109659:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;109739:49;109760:7;109777:1;109781:6;109739:20;:49::i;:::-;109801:22;109826:9;:18;109836:7;109826:18;;;;;;;;;;;;;;;;109801:43;;109881:6;109863:14;:24;;109855:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;110000:6;109983:14;:23;109962:9;:18;109972:7;109962:18;;;;;;;;;;;;;;;:44;;;;110117:6;110101:12;;:22;;;;;;;;;;;110178:1;110152:37;;110161:7;110152:37;;;110182:6;110152:37;;;;;;:::i;:::-;;;;;;;;110202:48;110222:7;110239:1;110243:6;110202:19;:48::i;:::-;109648:610;109583:675;;:::o;84155:342::-;84236:31;84280:12;84381:8;84378:1;84371:19;84436:3;84429:4;84426:1;84416:18;84412:28;84404:36;;84468:21;:4;:19;:21::i;:::-;84461:28;;;84155:342;;;;:::o;140402:212::-;140472:7;140510:1;140496:3;:10;;;;:15;140492:115;;140535:1;140528:8;;;;140492:115;140576:3;140593:1;140580:3;:10;;;;:14;;;;:::i;:::-;140576:19;;;;;;;;:::i;:::-;;;;;;;;;;140569:26;;140402:212;;;;:::o;80974:195::-;81035:21;81147:4;81137:14;;80974:195;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;:::o;88:117:1:-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:126::-;2897:7;2937:42;2930:5;2926:54;2915:65;;2860:126;;;:::o;2992:96::-;3029:7;3058:24;3076:5;3058:24;:::i;:::-;3047:35;;2992:96;;;:::o;3094:122::-;3167:24;3185:5;3167:24;:::i;:::-;3160:5;3157:35;3147:63;;3206:1;3203;3196:12;3147:63;3094:122;:::o;3222:139::-;3268:5;3306:6;3293:20;3284:29;;3322:33;3349:5;3322:33;:::i;:::-;3222:139;;;;:::o;3367:77::-;3404:7;3433:5;3422:16;;3367:77;;;:::o;3450:122::-;3523:24;3541:5;3523:24;:::i;:::-;3516:5;3513:35;3503:63;;3562:1;3559;3552:12;3503:63;3450:122;:::o;3578:139::-;3624:5;3662:6;3649:20;3640:29;;3678:33;3705:5;3678:33;:::i;:::-;3578:139;;;;:::o;3723:474::-;3791:6;3799;3848:2;3836:9;3827:7;3823:23;3819:32;3816:119;;;3854:79;;:::i;:::-;3816:119;3974:1;3999:53;4044:7;4035:6;4024:9;4020:22;3999:53;:::i;:::-;3989:63;;3945:117;4101:2;4127:53;4172:7;4163:6;4152:9;4148:22;4127:53;:::i;:::-;4117:63;;4072:118;3723:474;;;;;:::o;4203:118::-;4290:24;4308:5;4290:24;:::i;:::-;4285:3;4278:37;4203:118;;:::o;4327:222::-;4420:4;4458:2;4447:9;4443:18;4435:26;;4471:71;4539:1;4528:9;4524:17;4515:6;4471:71;:::i;:::-;4327:222;;;;:::o;4555:619::-;4632:6;4640;4648;4697:2;4685:9;4676:7;4672:23;4668:32;4665:119;;;4703:79;;:::i;:::-;4665:119;4823:1;4848:53;4893:7;4884:6;4873:9;4869:22;4848:53;:::i;:::-;4838:63;;4794:117;4950:2;4976:53;5021:7;5012:6;5001:9;4997:22;4976:53;:::i;:::-;4966:63;;4921:118;5078:2;5104:53;5149:7;5140:6;5129:9;5125:22;5104:53;:::i;:::-;5094:63;;5049:118;4555:619;;;;;:::o;5180:77::-;5217:7;5246:5;5235:16;;5180:77;;;:::o;5263:122::-;5336:24;5354:5;5336:24;:::i;:::-;5329:5;5326:35;5316:63;;5375:1;5372;5365:12;5316:63;5263:122;:::o;5391:139::-;5437:5;5475:6;5462:20;5453:29;;5491:33;5518:5;5491:33;:::i;:::-;5391:139;;;;:::o;5536:329::-;5595:6;5644:2;5632:9;5623:7;5619:23;5615:32;5612:119;;;5650:79;;:::i;:::-;5612:119;5770:1;5795:53;5840:7;5831:6;5820:9;5816:22;5795:53;:::i;:::-;5785:63;;5741:117;5536:329;;;;:::o;5871:118::-;5958:24;5976:5;5958:24;:::i;:::-;5953:3;5946:37;5871:118;;:::o;5995:222::-;6088:4;6126:2;6115:9;6111:18;6103:26;;6139:71;6207:1;6196:9;6192:17;6183:6;6139:71;:::i;:::-;5995:222;;;;:::o;6223:474::-;6291:6;6299;6348:2;6336:9;6327:7;6323:23;6319:32;6316:119;;;6354:79;;:::i;:::-;6316:119;6474:1;6499:53;6544:7;6535:6;6524:9;6520:22;6499:53;:::i;:::-;6489:63;;6445:117;6601:2;6627:53;6672:7;6663:6;6652:9;6648:22;6627:53;:::i;:::-;6617:63;;6572:118;6223:474;;;;;:::o;6703:86::-;6738:7;6778:4;6771:5;6767:16;6756:27;;6703:86;;;:::o;6795:112::-;6878:22;6894:5;6878:22;:::i;:::-;6873:3;6866:35;6795:112;;:::o;6913:214::-;7002:4;7040:2;7029:9;7025:18;7017:26;;7053:67;7117:1;7106:9;7102:17;7093:6;7053:67;:::i;:::-;6913:214;;;;:::o;7133:329::-;7192:6;7241:2;7229:9;7220:7;7216:23;7212:32;7209:119;;;7247:79;;:::i;:::-;7209:119;7367:1;7392:53;7437:7;7428:6;7417:9;7413:22;7392:53;:::i;:::-;7382:63;;7338:117;7133:329;;;;:::o;7468:::-;7527:6;7576:2;7564:9;7555:7;7551:23;7547:32;7544:119;;;7582:79;;:::i;:::-;7544:119;7702:1;7727:53;7772:7;7763:6;7752:9;7748:22;7727:53;:::i;:::-;7717:63;;7673:117;7468:329;;;;:::o;7803:118::-;7890:24;7908:5;7890:24;:::i;:::-;7885:3;7878:37;7803:118;;:::o;7927:222::-;8020:4;8058:2;8047:9;8043:18;8035:26;;8071:71;8139:1;8128:9;8124:17;8115:6;8071:71;:::i;:::-;7927:222;;;;:::o;8155:124::-;8220:7;8249:24;8267:5;8249:24;:::i;:::-;8238:35;;8155:124;;;:::o;8285:178::-;8386:52;8432:5;8386:52;:::i;:::-;8379:5;8376:63;8366:91;;8453:1;8450;8443:12;8366:91;8285:178;:::o;8469:195::-;8543:5;8581:6;8568:20;8559:29;;8597:61;8652:5;8597:61;:::i;:::-;8469:195;;;;:::o;8670:117::-;8779:1;8776;8769:12;8793:117;8902:1;8899;8892:12;8916:117;9025:1;9022;9015:12;9052:552;9109:8;9119:6;9169:3;9162:4;9154:6;9150:17;9146:27;9136:122;;9177:79;;:::i;:::-;9136:122;9290:6;9277:20;9267:30;;9320:18;9312:6;9309:30;9306:117;;;9342:79;;:::i;:::-;9306:117;9456:4;9448:6;9444:17;9432:29;;9510:3;9502:4;9494:6;9490:17;9480:8;9476:32;9473:41;9470:128;;;9517:79;;:::i;:::-;9470:128;9052:552;;;;;:::o;9610:1019::-;9735:6;9743;9751;9759;9767;9816:3;9804:9;9795:7;9791:23;9787:33;9784:120;;;9823:79;;:::i;:::-;9784:120;9943:1;9968:81;10041:7;10032:6;10021:9;10017:22;9968:81;:::i;:::-;9958:91;;9914:145;10098:2;10124:53;10169:7;10160:6;10149:9;10145:22;10124:53;:::i;:::-;10114:63;;10069:118;10226:2;10252:53;10297:7;10288:6;10277:9;10273:22;10252:53;:::i;:::-;10242:63;;10197:118;10382:2;10371:9;10367:18;10354:32;10413:18;10405:6;10402:30;10399:117;;;10435:79;;:::i;:::-;10399:117;10548:64;10604:7;10595:6;10584:9;10580:22;10548:64;:::i;:::-;10530:82;;;;10325:297;9610:1019;;;;;;;;:::o;10635:93::-;10671:7;10711:10;10704:5;10700:22;10689:33;;10635:93;;;:::o;10734:115::-;10819:23;10836:5;10819:23;:::i;:::-;10814:3;10807:36;10734:115;;:::o;10855:218::-;10946:4;10984:2;10973:9;10969:18;10961:26;;10997:69;11063:1;11052:9;11048:17;11039:6;10997:69;:::i;:::-;10855:218;;;;:::o;11079:118::-;11150:22;11166:5;11150:22;:::i;:::-;11143:5;11140:33;11130:61;;11187:1;11184;11177:12;11130:61;11079:118;:::o;11203:135::-;11247:5;11285:6;11272:20;11263:29;;11301:31;11326:5;11301:31;:::i;:::-;11203:135;;;;:::o;11344:1053::-;11446:6;11454;11462;11470;11478;11486;11535:3;11523:9;11514:7;11510:23;11506:33;11503:120;;;11542:79;;:::i;:::-;11503:120;11662:1;11687:53;11732:7;11723:6;11712:9;11708:22;11687:53;:::i;:::-;11677:63;;11633:117;11789:2;11815:53;11860:7;11851:6;11840:9;11836:22;11815:53;:::i;:::-;11805:63;;11760:118;11917:2;11943:53;11988:7;11979:6;11968:9;11964:22;11943:53;:::i;:::-;11933:63;;11888:118;12045:2;12071:51;12114:7;12105:6;12094:9;12090:22;12071:51;:::i;:::-;12061:61;;12016:116;12171:3;12198:53;12243:7;12234:6;12223:9;12219:22;12198:53;:::i;:::-;12188:63;;12142:119;12300:3;12327:53;12372:7;12363:6;12352:9;12348:22;12327:53;:::i;:::-;12317:63;;12271:119;11344:1053;;;;;;;;:::o;12403:1199::-;12514:6;12522;12530;12538;12546;12554;12562;12611:3;12599:9;12590:7;12586:23;12582:33;12579:120;;;12618:79;;:::i;:::-;12579:120;12738:1;12763:53;12808:7;12799:6;12788:9;12784:22;12763:53;:::i;:::-;12753:63;;12709:117;12865:2;12891:53;12936:7;12927:6;12916:9;12912:22;12891:53;:::i;:::-;12881:63;;12836:118;12993:2;13019:53;13064:7;13055:6;13044:9;13040:22;13019:53;:::i;:::-;13009:63;;12964:118;13121:2;13147:53;13192:7;13183:6;13172:9;13168:22;13147:53;:::i;:::-;13137:63;;13092:118;13249:3;13276:51;13319:7;13310:6;13299:9;13295:22;13276:51;:::i;:::-;13266:61;;13220:117;13376:3;13403:53;13448:7;13439:6;13428:9;13424:22;13403:53;:::i;:::-;13393:63;;13347:119;13505:3;13532:53;13577:7;13568:6;13557:9;13553:22;13532:53;:::i;:::-;13522:63;;13476:119;12403:1199;;;;;;;;;;:::o;13608:474::-;13676:6;13684;13733:2;13721:9;13712:7;13708:23;13704:32;13701:119;;;13739:79;;:::i;:::-;13701:119;13859:1;13884:53;13929:7;13920:6;13909:9;13905:22;13884:53;:::i;:::-;13874:63;;13830:117;13986:2;14012:53;14057:7;14048:6;14037:9;14033:22;14012:53;:::i;:::-;14002:63;;13957:118;13608:474;;;;;:::o;14088:120::-;14160:23;14177:5;14160:23;:::i;:::-;14153:5;14150:34;14140:62;;14198:1;14195;14188:12;14140:62;14088:120;:::o;14214:137::-;14259:5;14297:6;14284:20;14275:29;;14313:32;14339:5;14313:32;:::i;:::-;14214:137;;;;:::o;14357:472::-;14424:6;14432;14481:2;14469:9;14460:7;14456:23;14452:32;14449:119;;;14487:79;;:::i;:::-;14449:119;14607:1;14632:53;14677:7;14668:6;14657:9;14653:22;14632:53;:::i;:::-;14622:63;;14578:117;14734:2;14760:52;14804:7;14795:6;14784:9;14780:22;14760:52;:::i;:::-;14750:62;;14705:117;14357:472;;;;;:::o;14835:105::-;14910:23;14927:5;14910:23;:::i;:::-;14905:3;14898:36;14835:105;;:::o;14946:142::-;14983:7;15023:58;15016:5;15012:70;15001:81;;14946:142;;;:::o;15094:108::-;15171:24;15189:5;15171:24;:::i;:::-;15166:3;15159:37;15094:108;;:::o;15276:517::-;15429:4;15424:3;15420:14;15521:4;15514:5;15510:16;15504:23;15540:61;15595:4;15590:3;15586:14;15572:12;15540:61;:::i;:::-;15444:167;15694:4;15687:5;15683:16;15677:23;15713:63;15770:4;15765:3;15761:14;15747:12;15713:63;:::i;:::-;15621:165;15398:395;15276:517;;:::o;15799:334::-;15948:4;15986:2;15975:9;15971:18;15963:26;;15999:127;16123:1;16112:9;16108:17;16099:6;15999:127;:::i;:::-;15799:334;;;;:::o;16139:180::-;16187:77;16184:1;16177:88;16284:4;16281:1;16274:15;16308:4;16305:1;16298:15;16325:320;16369:6;16406:1;16400:4;16396:12;16386:22;;16453:1;16447:4;16443:12;16474:18;16464:81;;16530:4;16522:6;16518:17;16508:27;;16464:81;16592:2;16584:6;16581:14;16561:18;16558:38;16555:84;;16611:18;;:::i;:::-;16555:84;16376:269;16325:320;;;:::o;16651:234::-;16791:34;16787:1;16779:6;16775:14;16768:58;16860:17;16855:2;16847:6;16843:15;16836:42;16651:234;:::o;16891:366::-;17033:3;17054:67;17118:2;17113:3;17054:67;:::i;:::-;17047:74;;17130:93;17219:3;17130:93;:::i;:::-;17248:2;17243:3;17239:12;17232:19;;16891:366;;;:::o;17263:419::-;17429:4;17467:2;17456:9;17452:18;17444:26;;17516:9;17510:4;17506:20;17502:1;17491:9;17487:17;17480:47;17544:131;17670:4;17544:131;:::i;:::-;17536:139;;17263:419;;;:::o;17688:180::-;17736:77;17733:1;17726:88;17833:4;17830:1;17823:15;17857:4;17854:1;17847:15;17874:191;17914:3;17933:20;17951:1;17933:20;:::i;:::-;17928:25;;17967:20;17985:1;17967:20;:::i;:::-;17962:25;;18010:1;18007;18003:9;17996:16;;18031:3;18028:1;18025:10;18022:36;;;18038:18;;:::i;:::-;18022:36;17874:191;;;;:::o;18071:181::-;18211:33;18207:1;18199:6;18195:14;18188:57;18071:181;:::o;18258:366::-;18400:3;18421:67;18485:2;18480:3;18421:67;:::i;:::-;18414:74;;18497:93;18586:3;18497:93;:::i;:::-;18615:2;18610:3;18606:12;18599:19;;18258:366;;;:::o;18630:419::-;18796:4;18834:2;18823:9;18819:18;18811:26;;18883:9;18877:4;18873:20;18869:1;18858:9;18854:17;18847:47;18911:131;19037:4;18911:131;:::i;:::-;18903:139;;18630:419;;;:::o;19055:230::-;19195:34;19191:1;19183:6;19179:14;19172:58;19264:13;19259:2;19251:6;19247:15;19240:38;19055:230;:::o;19291:366::-;19433:3;19454:67;19518:2;19513:3;19454:67;:::i;:::-;19447:74;;19530:93;19619:3;19530:93;:::i;:::-;19648:2;19643:3;19639:12;19632:19;;19291:366;;;:::o;19663:419::-;19829:4;19867:2;19856:9;19852:18;19844:26;;19916:9;19910:4;19906:20;19902:1;19891:9;19887:17;19880:47;19944:131;20070:4;19944:131;:::i;:::-;19936:139;;19663:419;;;:::o;20088:168::-;20171:11;20205:6;20200:3;20193:19;20245:4;20240:3;20236:14;20221:29;;20088:168;;;;:::o;20262:146::-;20359:6;20354:3;20349;20336:30;20400:1;20391:6;20386:3;20382:16;20375:27;20262:146;;;:::o;20436:314::-;20532:3;20553:70;20616:6;20611:3;20553:70;:::i;:::-;20546:77;;20633:56;20682:6;20677:3;20670:5;20633:56;:::i;:::-;20714:29;20736:6;20714:29;:::i;:::-;20709:3;20705:39;20698:46;;20436:314;;;;;:::o;20756:771::-;20989:4;21027:3;21016:9;21012:19;21004:27;;21041:71;21109:1;21098:9;21094:17;21085:6;21041:71;:::i;:::-;21122:72;21190:2;21179:9;21175:18;21166:6;21122:72;:::i;:::-;21204;21272:2;21261:9;21257:18;21248:6;21204:72;:::i;:::-;21286;21354:2;21343:9;21339:18;21330:6;21286:72;:::i;:::-;21406:9;21400:4;21396:20;21390:3;21379:9;21375:19;21368:49;21434:86;21515:4;21506:6;21498;21434:86;:::i;:::-;21426:94;;20756:771;;;;;;;;;:::o;21533:143::-;21590:5;21621:6;21615:13;21606:22;;21637:33;21664:5;21637:33;:::i;:::-;21533:143;;;;:::o;21682:351::-;21752:6;21801:2;21789:9;21780:7;21776:23;21772:32;21769:119;;;21807:79;;:::i;:::-;21769:119;21927:1;21952:64;22008:7;21999:6;21988:9;21984:22;21952:64;:::i;:::-;21942:74;;21898:128;21682:351;;;;:::o;22039:223::-;22179:34;22175:1;22167:6;22163:14;22156:58;22248:6;22243:2;22235:6;22231:15;22224:31;22039:223;:::o;22268:366::-;22410:3;22431:67;22495:2;22490:3;22431:67;:::i;:::-;22424:74;;22507:93;22596:3;22507:93;:::i;:::-;22625:2;22620:3;22616:12;22609:19;;22268:366;;;:::o;22640:419::-;22806:4;22844:2;22833:9;22829:18;22821:26;;22893:9;22887:4;22883:20;22879:1;22868:9;22864:17;22857:47;22921:131;23047:4;22921:131;:::i;:::-;22913:139;;22640:419;;;:::o;23065:194::-;23105:4;23125:20;23143:1;23125:20;:::i;:::-;23120:25;;23159:20;23177:1;23159:20;:::i;:::-;23154:25;;23203:1;23200;23196:9;23188:17;;23227:1;23221:4;23218:11;23215:37;;;23232:18;;:::i;:::-;23215:37;23065:194;;;;:::o;23265:180::-;23313:77;23310:1;23303:88;23410:4;23407:1;23400:15;23434:4;23431:1;23424:15;23451:224;23591:34;23587:1;23579:6;23575:14;23568:58;23660:7;23655:2;23647:6;23643:15;23636:32;23451:224;:::o;23681:366::-;23823:3;23844:67;23908:2;23903:3;23844:67;:::i;:::-;23837:74;;23920:93;24009:3;23920:93;:::i;:::-;24038:2;24033:3;24029:12;24022:19;;23681:366;;;:::o;24053:419::-;24219:4;24257:2;24246:9;24242:18;24234:26;;24306:9;24300:4;24296:20;24292:1;24281:9;24277:17;24270:47;24334:131;24460:4;24334:131;:::i;:::-;24326:139;;24053:419;;;:::o;24478:179::-;24618:31;24614:1;24606:6;24602:14;24595:55;24478:179;:::o;24663:366::-;24805:3;24826:67;24890:2;24885:3;24826:67;:::i;:::-;24819:74;;24902:93;24991:3;24902:93;:::i;:::-;25020:2;25015:3;25011:12;25004:19;;24663:366;;;:::o;25035:419::-;25201:4;25239:2;25228:9;25224:18;25216:26;;25288:9;25282:4;25278:20;25274:1;25263:9;25259:17;25252:47;25316:131;25442:4;25316:131;:::i;:::-;25308:139;;25035:419;;;:::o;25460:553::-;25637:4;25675:3;25664:9;25660:19;25652:27;;25689:71;25757:1;25746:9;25742:17;25733:6;25689:71;:::i;:::-;25770:72;25838:2;25827:9;25823:18;25814:6;25770:72;:::i;:::-;25852;25920:2;25909:9;25905:18;25896:6;25852:72;:::i;:::-;25934;26002:2;25991:9;25987:18;25978:6;25934:72;:::i;:::-;25460:553;;;;;;;:::o;26019:175::-;26159:27;26155:1;26147:6;26143:14;26136:51;26019:175;:::o;26200:366::-;26342:3;26363:67;26427:2;26422:3;26363:67;:::i;:::-;26356:74;;26439:93;26528:3;26439:93;:::i;:::-;26557:2;26552:3;26548:12;26541:19;;26200:366;;;:::o;26572:419::-;26738:4;26776:2;26765:9;26761:18;26753:26;;26825:9;26819:4;26815:20;26811:1;26800:9;26796:17;26789:47;26853:131;26979:4;26853:131;:::i;:::-;26845:139;;26572:419;;;:::o;26997:179::-;27137:31;27133:1;27125:6;27121:14;27114:55;26997:179;:::o;27182:366::-;27324:3;27345:67;27409:2;27404:3;27345:67;:::i;:::-;27338:74;;27421:93;27510:3;27421:93;:::i;:::-;27539:2;27534:3;27530:12;27523:19;;27182:366;;;:::o;27554:419::-;27720:4;27758:2;27747:9;27743:18;27735:26;;27807:9;27801:4;27797:20;27793:1;27782:9;27778:17;27771:47;27835:131;27961:4;27835:131;:::i;:::-;27827:139;;27554:419;;;:::o;27979:775::-;28212:4;28250:3;28239:9;28235:19;28227:27;;28264:71;28332:1;28321:9;28317:17;28308:6;28264:71;:::i;:::-;28345:72;28413:2;28402:9;28398:18;28389:6;28345:72;:::i;:::-;28427;28495:2;28484:9;28480:18;28471:6;28427:72;:::i;:::-;28509;28577:2;28566:9;28562:18;28553:6;28509:72;:::i;:::-;28591:73;28659:3;28648:9;28644:19;28635:6;28591:73;:::i;:::-;28674;28742:3;28731:9;28727:19;28718:6;28674:73;:::i;:::-;27979:775;;;;;;;;;:::o;28760:180::-;28900:32;28896:1;28888:6;28884:14;28877:56;28760:180;:::o;28946:366::-;29088:3;29109:67;29173:2;29168:3;29109:67;:::i;:::-;29102:74;;29185:93;29274:3;29185:93;:::i;:::-;29303:2;29298:3;29294:12;29287:19;;28946:366;;;:::o;29318:419::-;29484:4;29522:2;29511:9;29507:18;29499:26;;29571:9;29565:4;29561:20;29557:1;29546:9;29542:17;29535:47;29599:131;29725:4;29599:131;:::i;:::-;29591:139;;29318:419;;;:::o;29743:177::-;29883:29;29879:1;29871:6;29867:14;29860:53;29743:177;:::o;29926:366::-;30068:3;30089:67;30153:2;30148:3;30089:67;:::i;:::-;30082:74;;30165:93;30254:3;30165:93;:::i;:::-;30283:2;30278:3;30274:12;30267:19;;29926:366;;;:::o;30298:419::-;30464:4;30502:2;30491:9;30487:18;30479:26;;30551:9;30545:4;30541:20;30537:1;30526:9;30522:17;30515:47;30579:131;30705:4;30579:131;:::i;:::-;30571:139;;30298:419;;;:::o;30723:235::-;30863:34;30859:1;30851:6;30847:14;30840:58;30932:18;30927:2;30919:6;30915:15;30908:43;30723:235;:::o;30964:366::-;31106:3;31127:67;31191:2;31186:3;31127:67;:::i;:::-;31120:74;;31203:93;31292:3;31203:93;:::i;:::-;31321:2;31316:3;31312:12;31305:19;;30964:366;;;:::o;31336:419::-;31502:4;31540:2;31529:9;31525:18;31517:26;;31589:9;31583:4;31579:20;31575:1;31564:9;31560:17;31553:47;31617:131;31743:4;31617:131;:::i;:::-;31609:139;;31336:419;;;:::o;31761:181::-;31901:33;31897:1;31889:6;31885:14;31878:57;31761:181;:::o;31948:366::-;32090:3;32111:67;32175:2;32170:3;32111:67;:::i;:::-;32104:74;;32187:93;32276:3;32187:93;:::i;:::-;32305:2;32300:3;32296:12;32289:19;;31948:366;;;:::o;32320:419::-;32486:4;32524:2;32513:9;32509:18;32501:26;;32573:9;32567:4;32563:20;32559:1;32548:9;32544:17;32537:47;32601:131;32727:4;32601:131;:::i;:::-;32593:139;;32320:419;;;:::o;32745:226::-;32885:34;32881:1;32873:6;32869:14;32862:58;32954:9;32949:2;32941:6;32937:15;32930:34;32745:226;:::o;32977:366::-;33119:3;33140:67;33204:2;33199:3;33140:67;:::i;:::-;33133:74;;33216:93;33305:3;33216:93;:::i;:::-;33334:2;33329:3;33325:12;33318:19;;32977:366;;;:::o;33349:419::-;33515:4;33553:2;33542:9;33538:18;33530:26;;33602:9;33596:4;33592:20;33588:1;33577:9;33573:17;33566:47;33630:131;33756:4;33630:131;:::i;:::-;33622:139;;33349:419;;;:::o;33774:225::-;33914:34;33910:1;33902:6;33898:14;33891:58;33983:8;33978:2;33970:6;33966:15;33959:33;33774:225;:::o;34005:366::-;34147:3;34168:67;34232:2;34227:3;34168:67;:::i;:::-;34161:74;;34244:93;34333:3;34244:93;:::i;:::-;34362:2;34357:3;34353:12;34346:19;;34005:366;;;:::o;34377:419::-;34543:4;34581:2;34570:9;34566:18;34558:26;;34630:9;34624:4;34620:20;34616:1;34605:9;34601:17;34594:47;34658:131;34784:4;34658:131;:::i;:::-;34650:139;;34377:419;;;:::o;34802:223::-;34942:34;34938:1;34930:6;34926:14;34919:58;35011:6;35006:2;34998:6;34994:15;34987:31;34802:223;:::o;35031:366::-;35173:3;35194:67;35258:2;35253:3;35194:67;:::i;:::-;35187:74;;35270:93;35359:3;35270:93;:::i;:::-;35388:2;35383:3;35379:12;35372:19;;35031:366;;;:::o;35403:419::-;35569:4;35607:2;35596:9;35592:18;35584:26;;35656:9;35650:4;35646:20;35642:1;35631:9;35627:17;35620:47;35684:131;35810:4;35684:131;:::i;:::-;35676:139;;35403:419;;;:::o;35828:221::-;35968:34;35964:1;35956:6;35952:14;35945:58;36037:4;36032:2;36024:6;36020:15;36013:29;35828:221;:::o;36055:366::-;36197:3;36218:67;36282:2;36277:3;36218:67;:::i;:::-;36211:74;;36294:93;36383:3;36294:93;:::i;:::-;36412:2;36407:3;36403:12;36396:19;;36055:366;;;:::o;36427:419::-;36593:4;36631:2;36620:9;36616:18;36608:26;;36680:9;36674:4;36670:20;36666:1;36655:9;36651:17;36644:47;36708:131;36834:4;36708:131;:::i;:::-;36700:139;;36427:419;;;:::o;36852:179::-;36992:31;36988:1;36980:6;36976:14;36969:55;36852:179;:::o;37037:366::-;37179:3;37200:67;37264:2;37259:3;37200:67;:::i;:::-;37193:74;;37276:93;37365:3;37276:93;:::i;:::-;37394:2;37389:3;37385:12;37378:19;;37037:366;;;:::o;37409:419::-;37575:4;37613:2;37602:9;37598:18;37590:26;;37662:9;37656:4;37652:20;37648:1;37637:9;37633:17;37626:47;37690:131;37816:4;37690:131;:::i;:::-;37682:139;;37409:419;;;:::o;37834:224::-;37974:34;37970:1;37962:6;37958:14;37951:58;38043:7;38038:2;38030:6;38026:15;38019:32;37834:224;:::o;38064:366::-;38206:3;38227:67;38291:2;38286:3;38227:67;:::i;:::-;38220:74;;38303:93;38392:3;38303:93;:::i;:::-;38421:2;38416:3;38412:12;38405:19;;38064:366;;;:::o;38436:419::-;38602:4;38640:2;38629:9;38625:18;38617:26;;38689:9;38683:4;38679:20;38675:1;38664:9;38660:17;38653:47;38717:131;38843:4;38717:131;:::i;:::-;38709:139;;38436:419;;;:::o;38861:222::-;39001:34;38997:1;38989:6;38985:14;38978:58;39070:5;39065:2;39057:6;39053:15;39046:30;38861:222;:::o;39089:366::-;39231:3;39252:67;39316:2;39311:3;39252:67;:::i;:::-;39245:74;;39328:93;39417:3;39328:93;:::i;:::-;39446:2;39441:3;39437:12;39430:19;;39089:366;;;:::o;39461:419::-;39627:4;39665:2;39654:9;39650:18;39642:26;;39714:9;39708:4;39704:20;39700:1;39689:9;39685:17;39678:47;39742:131;39868:4;39742:131;:::i;:::-;39734:139;;39461:419;;;:::o;39886:225::-;40026:34;40022:1;40014:6;40010:14;40003:58;40095:8;40090:2;40082:6;40078:15;40071:33;39886:225;:::o;40117:366::-;40259:3;40280:67;40344:2;40339:3;40280:67;:::i;:::-;40273:74;;40356:93;40445:3;40356:93;:::i;:::-;40474:2;40469:3;40465:12;40458:19;;40117:366;;;:::o;40489:419::-;40655:4;40693:2;40682:9;40678:18;40670:26;;40742:9;40736:4;40732:20;40728:1;40717:9;40713:17;40706:47;40770:131;40896:4;40770:131;:::i;:::-;40762:139;;40489:419;;;:::o;40914:172::-;41054:24;41050:1;41042:6;41038:14;41031:48;40914:172;:::o;41092:366::-;41234:3;41255:67;41319:2;41314:3;41255:67;:::i;:::-;41248:74;;41331:93;41420:3;41331:93;:::i;:::-;41449:2;41444:3;41440:12;41433:19;;41092:366;;;:::o;41464:419::-;41630:4;41668:2;41657:9;41653:18;41645:26;;41717:9;41711:4;41707:20;41703:1;41692:9;41688:17;41681:47;41745:131;41871:4;41745:131;:::i;:::-;41737:139;;41464:419;;;:::o;41889:179::-;42029:31;42025:1;42017:6;42013:14;42006:55;41889:179;:::o;42074:366::-;42216:3;42237:67;42301:2;42296:3;42237:67;:::i;:::-;42230:74;;42313:93;42402:3;42313:93;:::i;:::-;42431:2;42426:3;42422:12;42415:19;;42074:366;;;:::o;42446:419::-;42612:4;42650:2;42639:9;42635:18;42627:26;;42699:9;42693:4;42689:20;42685:1;42674:9;42670:17;42663:47;42727:131;42853:4;42727:131;:::i;:::-;42719:139;;42446:419;;;:::o;42871:332::-;42992:4;43030:2;43019:9;43015:18;43007:26;;43043:71;43111:1;43100:9;43096:17;43087:6;43043:71;:::i;:::-;43124:72;43192:2;43181:9;43177:18;43168:6;43124:72;:::i;:::-;42871:332;;;;;:::o;43209:148::-;43311:11;43348:3;43333:18;;43209:148;;;;:::o;43363:173::-;43503:25;43499:1;43491:6;43487:14;43480:49;43363:173;:::o;43542:402::-;43702:3;43723:85;43805:2;43800:3;43723:85;:::i;:::-;43716:92;;43817:93;43906:3;43817:93;:::i;:::-;43935:2;43930:3;43926:12;43919:19;;43542:402;;;:::o;43950:390::-;44056:3;44084:39;44117:5;44084:39;:::i;:::-;44139:89;44221:6;44216:3;44139:89;:::i;:::-;44132:96;;44237:65;44295:6;44290:3;44283:4;44276:5;44272:16;44237:65;:::i;:::-;44327:6;44322:3;44318:16;44311:23;;44060:280;43950:390;;;;:::o;44346:167::-;44486:19;44482:1;44474:6;44470:14;44463:43;44346:167;:::o;44519:402::-;44679:3;44700:85;44782:2;44777:3;44700:85;:::i;:::-;44693:92;;44794:93;44883:3;44794:93;:::i;:::-;44912:2;44907:3;44903:12;44896:19;;44519:402;;;:::o;44927:967::-;45309:3;45331:148;45475:3;45331:148;:::i;:::-;45324:155;;45496:95;45587:3;45578:6;45496:95;:::i;:::-;45489:102;;45608:148;45752:3;45608:148;:::i;:::-;45601:155;;45773:95;45864:3;45855:6;45773:95;:::i;:::-;45766:102;;45885:3;45878:10;;44927:967;;;;;:::o;45900:664::-;46105:4;46143:3;46132:9;46128:19;46120:27;;46157:71;46225:1;46214:9;46210:17;46201:6;46157:71;:::i;:::-;46238:72;46306:2;46295:9;46291:18;46282:6;46238:72;:::i;:::-;46320;46388:2;46377:9;46373:18;46364:6;46320:72;:::i;:::-;46402;46470:2;46459:9;46455:18;46446:6;46402:72;:::i;:::-;46484:73;46552:3;46541:9;46537:19;46528:6;46484:73;:::i;:::-;45900:664;;;;;;;;:::o;46570:180::-;46618:77;46615:1;46608:88;46715:4;46712:1;46705:15;46739:4;46736:1;46729:15;46756:185;46796:1;46813:20;46831:1;46813:20;:::i;:::-;46808:25;;46847:20;46865:1;46847:20;:::i;:::-;46842:25;;46886:1;46876:35;;46891:18;;:::i;:::-;46876:35;46933:1;46930;46926:9;46921:14;;46756:185;;;;:::o;46947:170::-;47087:22;47083:1;47075:6;47071:14;47064:46;46947:170;:::o;47123:366::-;47265:3;47286:67;47350:2;47345:3;47286:67;:::i;:::-;47279:74;;47362:93;47451:3;47362:93;:::i;:::-;47480:2;47475:3;47471:12;47464:19;;47123:366;;;:::o;47495:419::-;47661:4;47699:2;47688:9;47684:18;47676:26;;47748:9;47742:4;47738:20;47734:1;47723:9;47719:17;47712:47;47776:131;47902:4;47776:131;:::i;:::-;47768:139;;47495:419;;;:::o;47920:166::-;48060:18;48056:1;48048:6;48044:14;48037:42;47920:166;:::o;48092:366::-;48234:3;48255:67;48319:2;48314:3;48255:67;:::i;:::-;48248:74;;48331:93;48420:3;48331:93;:::i;:::-;48449:2;48444:3;48440:12;48433:19;;48092:366;;;:::o;48464:419::-;48630:4;48668:2;48657:9;48653:18;48645:26;;48717:9;48711:4;48707:20;48703:1;48692:9;48688:17;48681:47;48745:131;48871:4;48745:131;:::i;:::-;48737:139;;48464:419;;;:::o;48889:214::-;49029:66;49025:1;49017:6;49013:14;49006:90;48889:214;:::o;49109:400::-;49269:3;49290:84;49372:1;49367:3;49290:84;:::i;:::-;49283:91;;49383:93;49472:3;49383:93;:::i;:::-;49501:1;49496:3;49492:11;49485:18;;49109:400;;;:::o;49515:79::-;49554:7;49583:5;49572:16;;49515:79;;;:::o;49600:157::-;49705:45;49725:24;49743:5;49725:24;:::i;:::-;49705:45;:::i;:::-;49700:3;49693:58;49600:157;;:::o;49763:663::-;50004:3;50026:148;50170:3;50026:148;:::i;:::-;50019:155;;50184:75;50255:3;50246:6;50184:75;:::i;:::-;50284:2;50279:3;50275:12;50268:19;;50297:75;50368:3;50359:6;50297:75;:::i;:::-;50397:2;50392:3;50388:12;50381:19;;50417:3;50410:10;;49763:663;;;;;:::o;50432:545::-;50605:4;50643:3;50632:9;50628:19;50620:27;;50657:71;50725:1;50714:9;50710:17;50701:6;50657:71;:::i;:::-;50738:68;50802:2;50791:9;50787:18;50778:6;50738:68;:::i;:::-;50816:72;50884:2;50873:9;50869:18;50860:6;50816:72;:::i;:::-;50898;50966:2;50955:9;50951:18;50942:6;50898:72;:::i;:::-;50432:545;;;;;;;:::o;50983:180::-;51031:77;51028:1;51021:88;51128:4;51125:1;51118:15;51152:4;51149:1;51142:15;51169:174;51309:26;51305:1;51297:6;51293:14;51286:50;51169:174;:::o;51349:366::-;51491:3;51512:67;51576:2;51571:3;51512:67;:::i;:::-;51505:74;;51588:93;51677:3;51588:93;:::i;:::-;51706:2;51701:3;51697:12;51690:19;;51349:366;;;:::o;51721:419::-;51887:4;51925:2;51914:9;51910:18;51902:26;;51974:9;51968:4;51964:20;51960:1;51949:9;51945:17;51938:47;52002:131;52128:4;52002:131;:::i;:::-;51994:139;;51721:419;;;:::o;52146:181::-;52286:33;52282:1;52274:6;52270:14;52263:57;52146:181;:::o;52333:366::-;52475:3;52496:67;52560:2;52555:3;52496:67;:::i;:::-;52489:74;;52572:93;52661:3;52572:93;:::i;:::-;52690:2;52685:3;52681:12;52674:19;;52333:366;;;:::o;52705:419::-;52871:4;52909:2;52898:9;52894:18;52886:26;;52958:9;52952:4;52948:20;52944:1;52933:9;52929:17;52922:47;52986:131;53112:4;52986:131;:::i;:::-;52978:139;;52705:419;;;:::o;53130:221::-;53270:34;53266:1;53258:6;53254:14;53247:58;53339:4;53334:2;53326:6;53322:15;53315:29;53130:221;:::o;53357:366::-;53499:3;53520:67;53584:2;53579:3;53520:67;:::i;:::-;53513:74;;53596:93;53685:3;53596:93;:::i;:::-;53714:2;53709:3;53705:12;53698:19;;53357:366;;;:::o;53729:419::-;53895:4;53933:2;53922:9;53918:18;53910:26;;53982:9;53976:4;53972:20;53968:1;53957:9;53953:17;53946:47;54010:131;54136:4;54010:131;:::i;:::-;54002:139;;53729:419;;;:::o;54154:410::-;54194:7;54217:20;54235:1;54217:20;:::i;:::-;54212:25;;54251:20;54269:1;54251:20;:::i;:::-;54246:25;;54306:1;54303;54299:9;54328:30;54346:11;54328:30;:::i;:::-;54317:41;;54507:1;54498:7;54494:15;54491:1;54488:22;54468:1;54461:9;54441:83;54418:139;;54537:18;;:::i;:::-;54418:139;54202:362;54154:410;;;;:::o;54570:180::-;54618:77;54615:1;54608:88;54715:4;54712:1;54705:15;54739:4;54736:1;54729:15;54756:171;54795:3;54818:24;54836:5;54818:24;:::i;:::-;54809:33;;54864:4;54857:5;54854:15;54851:41;;54872:18;;:::i;:::-;54851:41;54919:1;54912:5;54908:13;54901:20;;54756:171;;;:::o;54933:182::-;55073:34;55069:1;55061:6;55057:14;55050:58;54933:182;:::o;55121:366::-;55263:3;55284:67;55348:2;55343:3;55284:67;:::i;:::-;55277:74;;55360:93;55449:3;55360:93;:::i;:::-;55478:2;55473:3;55469:12;55462:19;;55121:366;;;:::o;55493:419::-;55659:4;55697:2;55686:9;55682:18;55674:26;;55746:9;55740:4;55736:20;55732:1;55721:9;55717:17;55710:47;55774:131;55900:4;55774:131;:::i;:::-;55766:139;;55493:419;;;:::o;55918:220::-;56058:34;56054:1;56046:6;56042:14;56035:58;56127:3;56122:2;56114:6;56110:15;56103:28;55918:220;:::o;56144:366::-;56286:3;56307:67;56371:2;56366:3;56307:67;:::i;:::-;56300:74;;56383:93;56472:3;56383:93;:::i;:::-;56501:2;56496:3;56492:12;56485:19;;56144:366;;;:::o;56516:419::-;56682:4;56720:2;56709:9;56705:18;56697:26;;56769:9;56763:4;56759:20;56755:1;56744:9;56740:17;56733:47;56797:131;56923:4;56797:131;:::i;:::-;56789:139;;56516:419;;;:::o;56941:221::-;57081:34;57077:1;57069:6;57065:14;57058:58;57150:4;57145:2;57137:6;57133:15;57126:29;56941:221;:::o;57168:366::-;57310:3;57331:67;57395:2;57390:3;57331:67;:::i;:::-;57324:74;;57407:93;57496:3;57407:93;:::i;:::-;57525:2;57520:3;57516:12;57509:19;;57168:366;;;:::o;57540:419::-;57706:4;57744:2;57733:9;57729:18;57721:26;;57793:9;57787:4;57783:20;57779:1;57768:9;57764:17;57757:47;57821:131;57947:4;57821:131;:::i;:::-;57813:139;;57540:419;;;:::o

Swarm Source

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