ETH Price: $2,287.20 (-3.61%)

Token

Matchi Token (MCH)
 

Overview

Max Total Supply

100,000,000 MCH

Holders

279 (0.00%)

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
100 MCH

Value
$0.00
0xc85a70f53a46037319623ab656943f4490b3cc26
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

MATCHI is a Web3 dance game with Token, NFT, DAO. Players use NFT Dancer to enter the game and get rewards by dancing. MCH is an in-game asset, 400 million tokens were allocated in the early stage, 600 million tokens are rewarded through the game, and there is a burn mechanism at the same time.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
MatchiToken

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-08-18
*/

// SPDX-License-Identifier: MIT
// File: @openzeppelin/contracts/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/contracts/utils/math/SafeCast.sol


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

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) {
        require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits");
        return int248(value);
    }

    /**
     * @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) {
        require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits");
        return int240(value);
    }

    /**
     * @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) {
        require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits");
        return int232(value);
    }

    /**
     * @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) {
        require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits");
        return int224(value);
    }

    /**
     * @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) {
        require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits");
        return int216(value);
    }

    /**
     * @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) {
        require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits");
        return int208(value);
    }

    /**
     * @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) {
        require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits");
        return int200(value);
    }

    /**
     * @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) {
        require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits");
        return int192(value);
    }

    /**
     * @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) {
        require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits");
        return int184(value);
    }

    /**
     * @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) {
        require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits");
        return int176(value);
    }

    /**
     * @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) {
        require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits");
        return int168(value);
    }

    /**
     * @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) {
        require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits");
        return int160(value);
    }

    /**
     * @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) {
        require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits");
        return int152(value);
    }

    /**
     * @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) {
        require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits");
        return int144(value);
    }

    /**
     * @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) {
        require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits");
        return int136(value);
    }

    /**
     * @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) {
        require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
        return int128(value);
    }

    /**
     * @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) {
        require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits");
        return int120(value);
    }

    /**
     * @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) {
        require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits");
        return int112(value);
    }

    /**
     * @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) {
        require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits");
        return int104(value);
    }

    /**
     * @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) {
        require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits");
        return int96(value);
    }

    /**
     * @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) {
        require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits");
        return int88(value);
    }

    /**
     * @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) {
        require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits");
        return int80(value);
    }

    /**
     * @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) {
        require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits");
        return int72(value);
    }

    /**
     * @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) {
        require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
        return int64(value);
    }

    /**
     * @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) {
        require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits");
        return int56(value);
    }

    /**
     * @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) {
        require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits");
        return int48(value);
    }

    /**
     * @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) {
        require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits");
        return int40(value);
    }

    /**
     * @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) {
        require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
        return int32(value);
    }

    /**
     * @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) {
        require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits");
        return int24(value);
    }

    /**
     * @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) {
        require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
        return int16(value);
    }

    /**
     * @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) {
        require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
        return int8(value);
    }

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

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


// OpenZeppelin Contracts (last updated v4.7.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. It 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)`.
        // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.
        // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.
        // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a
        // good first aproximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1;
        uint256 x = a;
        if (x >> 128 > 0) {
            x >>= 128;
            result <<= 64;
        }
        if (x >> 64 > 0) {
            x >>= 64;
            result <<= 32;
        }
        if (x >> 32 > 0) {
            x >>= 32;
            result <<= 16;
        }
        if (x >> 16 > 0) {
            x >>= 16;
            result <<= 8;
        }
        if (x >> 8 > 0) {
            x >>= 8;
            result <<= 4;
        }
        if (x >> 4 > 0) {
            x >>= 4;
            result <<= 2;
        }
        if (x >> 2 > 0) {
            result <<= 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) {
        uint256 result = sqrt(a);
        if (rounding == Rounding.Up && result * result < a) {
            result += 1;
        }
        return result;
    }
}

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


// OpenZeppelin Contracts (last updated v4.5.0) (utils/Checkpoints.sol)
pragma solidity ^0.8.0;



/**
 * @dev This library defines the `History` struct, for checkpointing values as they change at different points in
 * time, and later looking up past values by block number. See {Votes} as an example.
 *
 * To create a history of checkpoints define a variable type `Checkpoints.History` in your contract, and store a new
 * checkpoint for the current transaction block using the {push} function.
 *
 * _Available since v4.5._
 */
library Checkpoints {
    struct Checkpoint {
        uint32 _blockNumber;
        uint224 _value;
    }

    struct History {
        Checkpoint[] _checkpoints;
    }

    /**
     * @dev Returns the value in the latest checkpoint, or zero if there are no checkpoints.
     */
    function latest(History storage self) internal view returns (uint256) {
        uint256 pos = self._checkpoints.length;
        return pos == 0 ? 0 : self._checkpoints[pos - 1]._value;
    }

    /**
     * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
     * before it is returned, or zero otherwise.
     */
    function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
        require(blockNumber < block.number, "Checkpoints: block not yet mined");

        uint256 high = self._checkpoints.length;
        uint256 low = 0;
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (self._checkpoints[mid]._blockNumber > blockNumber) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high == 0 ? 0 : self._checkpoints[high - 1]._value;
    }

    /**
     * @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block.
     *
     * Returns previous value and new value.
     */
    function push(History storage self, uint256 value) internal returns (uint256, uint256) {
        uint256 pos = self._checkpoints.length;
        uint256 old = latest(self);
        if (pos > 0 && self._checkpoints[pos - 1]._blockNumber == block.number) {
            self._checkpoints[pos - 1]._value = SafeCast.toUint224(value);
        } else {
            self._checkpoints.push(
                Checkpoint({_blockNumber: SafeCast.toUint32(block.number), _value: SafeCast.toUint224(value)})
            );
        }
        return (old, value);
    }

    /**
     * @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will
     * be set to `op(latest, delta)`.
     *
     * Returns previous value and new value.
     */
    function push(
        History storage self,
        function(uint256, uint256) view returns (uint256) op,
        uint256 delta
    ) internal returns (uint256, uint256) {
        return push(self, op(latest(self), delta));
    }
}

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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


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

pragma solidity ^0.8.0;


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

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


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

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_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) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

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

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

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

    /**
     * @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/contracts/utils/cryptography/ECDSA.sol


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

    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");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' 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) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        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 if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // 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))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } 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 (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // 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/contracts/utils/cryptography/draft-EIP712.sol


// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-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/contracts/access/IAccessControl.sol


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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


// OpenZeppelin Contracts (last updated v4.6.0) (utils/introspection/IERC1820Registry.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the global ERC1820 Registry, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
 * implementers for interfaces in this registry, as well as query support.
 *
 * Implementers may be shared by multiple accounts, and can also implement more
 * than a single interface for each account. Contracts can implement interfaces
 * for themselves, but externally-owned accounts (EOA) must delegate this to a
 * contract.
 *
 * {IERC165} interfaces can also be queried via the registry.
 *
 * For an in-depth explanation and source code analysis, see the EIP text.
 */
interface IERC1820Registry {
    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);

    event ManagerChanged(address indexed account, address indexed newManager);

    /**
     * @dev Sets `newManager` as the manager for `account`. A manager of an
     * account is able to set interface implementers for it.
     *
     * By default, each account is its own manager. Passing a value of `0x0` in
     * `newManager` will reset the manager to this initial state.
     *
     * Emits a {ManagerChanged} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     */
    function setManager(address account, address newManager) external;

    /**
     * @dev Returns the manager for `account`.
     *
     * See {setManager}.
     */
    function getManager(address account) external view returns (address);

    /**
     * @dev Sets the `implementer` contract as ``account``'s implementer for
     * `interfaceHash`.
     *
     * `account` being the zero address is an alias for the caller's address.
     * The zero address can also be used in `implementer` to remove an old one.
     *
     * See {interfaceHash} to learn how these are created.
     *
     * Emits an {InterfaceImplementerSet} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
     * end in 28 zeroes).
     * - `implementer` must implement {IERC1820Implementer} and return true when
     * queried for support, unless `implementer` is the caller. See
     * {IERC1820Implementer-canImplementInterfaceForAddress}.
     */
    function setInterfaceImplementer(
        address account,
        bytes32 _interfaceHash,
        address implementer
    ) external;

    /**
     * @dev Returns the implementer of `interfaceHash` for `account`. If no such
     * implementer is registered, returns the zero address.
     *
     * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
     * zeroes), `account` will be queried for support of it.
     *
     * `account` being the zero address is an alias for the caller's address.
     */
    function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);

    /**
     * @dev Returns the interface hash for an `interfaceName`, as defined in the
     * corresponding
     * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
     */
    function interfaceHash(string calldata interfaceName) external pure returns (bytes32);

    /**
     * @notice Updates the cache with whether the contract implements an ERC165 interface or not.
     * @param account Address of the contract for which to update the cache.
     * @param interfaceId ERC165 interface for which to update the cache.
     */
    function updateERC165Cache(address account, bytes4 interfaceId) external;

    /**
     * @notice Checks whether a contract implements an ERC165 interface or not.
     * If the result is not cached a direct lookup on the contract address is performed.
     * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
     * {updateERC165Cache} with the contract address.
     * @param account Address of the contract to check.
     * @param interfaceId ERC165 interface to check.
     * @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);

    /**
     * @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
     * @param account Address of the contract to check.
     * @param interfaceId ERC165 interface to check.
     * @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
}

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


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

pragma solidity ^0.8.0;

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

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

// File: @openzeppelin/contracts/governance/utils/Votes.sol


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






/**
 * @dev This is a base abstract contract that tracks voting units, which are a measure of voting power that can be
 * transferred, and provides a system of vote delegation, where an account can delegate its voting units to a sort of
 * "representative" that will pool delegated voting units from different accounts and can then use it to vote in
 * decisions. In fact, voting units _must_ be delegated in order to count as actual votes, and an account has to
 * delegate those votes to itself if it wishes to participate in decisions and does not have a trusted representative.
 *
 * This contract is often combined with a token contract such that voting units correspond to token units. For an
 * example, see {ERC721Votes}.
 *
 * The full history of delegate votes is tracked on-chain so that governance protocols can consider votes as distributed
 * at a particular block number to protect against flash loans and double voting. The opt-in delegate system makes the
 * cost of this history tracking optional.
 *
 * When using this module the derived contract must implement {_getVotingUnits} (for example, make it return
 * {ERC721-balanceOf}), and can use {_transferVotingUnits} to track a change in the distribution of those units (in the
 * previous example, it would be included in {ERC721-_beforeTokenTransfer}).
 *
 * _Available since v4.5._
 */
abstract contract Votes is IVotes, Context, EIP712 {
    using Checkpoints for Checkpoints.History;
    using Counters for Counters.Counter;

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

    mapping(address => address) private _delegation;
    mapping(address => Checkpoints.History) private _delegateCheckpoints;
    Checkpoints.History private _totalCheckpoints;

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

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) public view virtual override returns (uint256) {
        return _delegateCheckpoints[account].latest();
    }

    /**
     * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).
     *
     * Requirements:
     *
     * - `blockNumber` must have been already mined
     */
    function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
        return _delegateCheckpoints[account].getAtBlock(blockNumber);
    }

    /**
     * @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.
     *
     * Requirements:
     *
     * - `blockNumber` must have been already mined
     */
    function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {
        require(blockNumber < block.number, "Votes: block not yet mined");
        return _totalCheckpoints.getAtBlock(blockNumber);
    }

    /**
     * @dev Returns the current total supply of votes.
     */
    function _getTotalSupply() internal view virtual returns (uint256) {
        return _totalCheckpoints.latest();
    }

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) public view virtual override returns (address) {
        return _delegation[account];
    }

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) public virtual override {
        address account = _msgSender();
        _delegate(account, 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, "Votes: signature expired");
        address signer = ECDSA.recover(
            _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
            v,
            r,
            s
        );
        require(nonce == _useNonce(signer), "Votes: invalid nonce");
        _delegate(signer, delegatee);
    }

    /**
     * @dev Delegate all of `account`'s voting units to `delegatee`.
     *
     * Emits events {DelegateChanged} and {DelegateVotesChanged}.
     */
    function _delegate(address account, address delegatee) internal virtual {
        address oldDelegate = delegates(account);
        _delegation[account] = delegatee;

        emit DelegateChanged(account, oldDelegate, delegatee);
        _moveDelegateVotes(oldDelegate, delegatee, _getVotingUnits(account));
    }

    /**
     * @dev Transfers, mints, or burns voting units. To register a mint, `from` should be zero. To register a burn, `to`
     * should be zero. Total supply of voting units will be adjusted with mints and burns.
     */
    function _transferVotingUnits(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        if (from == address(0)) {
            _totalCheckpoints.push(_add, amount);
        }
        if (to == address(0)) {
            _totalCheckpoints.push(_subtract, amount);
        }
        _moveDelegateVotes(delegates(from), delegates(to), amount);
    }

    /**
     * @dev Moves delegated votes from one delegate to another.
     */
    function _moveDelegateVotes(
        address from,
        address to,
        uint256 amount
    ) private {
        if (from != to && amount > 0) {
            if (from != address(0)) {
                (uint256 oldValue, uint256 newValue) = _delegateCheckpoints[from].push(_subtract, amount);
                emit DelegateVotesChanged(from, oldValue, newValue);
            }
            if (to != address(0)) {
                (uint256 oldValue, uint256 newValue) = _delegateCheckpoints[to].push(_add, amount);
                emit DelegateVotesChanged(to, oldValue, newValue);
            }
        }
    }

    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 Consumes a nonce.
     *
     * Returns the current value and increments nonce.
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }

    /**
     * @dev Returns an address nonce.
     */
    function nonces(address owner) public view virtual returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev Returns the contract's {EIP712} domain separator.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev Must return the voting units held by an account.
     */
    function _getVotingUnits(address) internal view virtual returns (uint256);
}

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


// OpenZeppelin Contracts (last updated v4.7.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(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

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

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * 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/contracts/security/Pausable.sol


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

pragma solidity ^0.8.0;


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

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

    bool private _paused;

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/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/contracts/token/ERC777/IERC777Sender.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Sender.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC777TokensSender standard as defined in the EIP.
 *
 * {IERC777} Token holders can be notified of operations performed on their
 * tokens by having a contract implement this interface (contract holders can be
 * their own implementer) and registering it on the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
 *
 * See {IERC1820Registry} and {ERC1820Implementer}.
 */
interface IERC777Sender {
    /**
     * @dev Called by an {IERC777} token contract whenever a registered holder's
     * (`from`) tokens are about to be moved or destroyed. The type of operation
     * is conveyed by `to` being the zero address or not.
     *
     * This call occurs _before_ the token contract's state is updated, so
     * {IERC777-balanceOf}, etc., can be used to query the pre-operation state.
     *
     * This function may revert to prevent the operation from being executed.
     */
    function tokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}

// File: @openzeppelin/contracts/token/ERC777/IERC777Recipient.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
 *
 * Accounts can be notified of {IERC777} tokens being sent to them by having a
 * contract implement this interface (contract holders can be their own
 * implementer) and registering it on the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
 *
 * See {IERC1820Registry} and {ERC1820Implementer}.
 */
interface IERC777Recipient {
    /**
     * @dev Called by an {IERC777} token contract whenever tokens are being
     * moved or created into a registered account (`to`). The type of operation
     * is conveyed by `from` being the zero address or not.
     *
     * This call occurs _after_ the token contract's state is updated, so
     * {IERC777-balanceOf}, etc., can be used to query the post-operation state.
     *
     * This function may revert to prevent the operation from being executed.
     */
    function tokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}

// File: @openzeppelin/contracts/token/ERC777/IERC777.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC777/IERC777.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC777Token standard as defined in the EIP.
 *
 * This contract uses the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
 * token holders and recipients react to token movements by using setting implementers
 * for the associated interfaces in said registry. See {IERC1820Registry} and
 * {ERC1820Implementer}.
 */
interface IERC777 {
    /**
     * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`.
     *
     * Note that some additional user `data` and `operatorData` can be logged in the event.
     */
    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);

    /**
     * @dev Emitted when `operator` destroys `amount` tokens from `account`.
     *
     * Note that some additional user `data` and `operatorData` can be logged in the event.
     */
    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);

    /**
     * @dev Emitted when `operator` is made operator for `tokenHolder`
     */
    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);

    /**
     * @dev Emitted when `operator` is revoked its operator status for `tokenHolder`
     */
    event RevokedOperator(address indexed operator, address indexed tokenHolder);

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

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the smallest part of the token that is not divisible. This
     * means all token operations (creation, movement and destruction) must have
     * amounts that are a multiple of this number.
     *
     * For most token contracts, this value will equal 1.
     */
    function granularity() external view returns (uint256);

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

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

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * If send or receive hooks are registered for the caller and `recipient`,
     * the corresponding functions will be called with `data` and empty
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function send(
        address recipient,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the
     * total supply.
     *
     * If a send hook is registered for the caller, the corresponding function
     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     */
    function burn(uint256 amount, bytes calldata data) external;

    /**
     * @dev Returns true if an account is an operator of `tokenHolder`.
     * Operators can send and burn tokens on behalf of their owners. All
     * accounts are their own operator.
     *
     * See {operatorSend} and {operatorBurn}.
     */
    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);

    /**
     * @dev Make an account an operator of the caller.
     *
     * See {isOperatorFor}.
     *
     * Emits an {AuthorizedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function authorizeOperator(address operator) external;

    /**
     * @dev Revoke an account's operator status for the caller.
     *
     * See {isOperatorFor} and {defaultOperators}.
     *
     * Emits a {RevokedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function revokeOperator(address operator) external;

    /**
     * @dev Returns the list of default operators. These accounts are operators
     * for all token holders, even if {authorizeOperator} was never called on
     * them.
     *
     * This list is immutable, but individual holders may revoke these via
     * {revokeOperator}, in which case {isOperatorFor} will return false.
     */
    function defaultOperators() external view returns (address[] memory);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
     * be an operator of `sender`.
     *
     * If send or receive hooks are registered for `sender` and `recipient`,
     * the corresponding functions will be called with `data` and
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - `sender` cannot be the zero address.
     * - `sender` must have at least `amount` tokens.
     * - the caller must be an operator for `sender`.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the total supply.
     * The caller must be an operator of `account`.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `data` and `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     * - the caller must be an operator for `account`.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    event Sent(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );
}

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


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC777/ERC777.sol)

pragma solidity ^0.8.0;








/**
 * @dev Implementation of the {IERC777} 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}.
 *
 * Support for ERC20 is included in this contract, as specified by the EIP: both
 * the ERC777 and ERC20 interfaces can be safely used when interacting with it.
 * Both {IERC777-Sent} and {IERC20-Transfer} events are emitted on token
 * movements.
 *
 * Additionally, the {IERC777-granularity} value is hard-coded to `1`, meaning that there
 * are no special restrictions in the amount of tokens that created, moved, or
 * destroyed. This makes integration with ERC20 applications seamless.
 */
contract ERC777 is Context, IERC777, IERC20 {
    using Address for address;

    IERC1820Registry internal constant _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);

    mapping(address => uint256) private _balances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
    bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");

    // This isn't ever read from - it's only used to respond to the defaultOperators query.
    address[] private _defaultOperatorsArray;

    // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
    mapping(address => bool) private _defaultOperators;

    // For each account, a mapping of its operators and revoked default operators.
    mapping(address => mapping(address => bool)) private _operators;
    mapping(address => mapping(address => bool)) private _revokedDefaultOperators;

    // ERC20-allowances
    mapping(address => mapping(address => uint256)) private _allowances;

    /**
     * @dev `defaultOperators` may be an empty array.
     */
    constructor(
        string memory name_,
        string memory symbol_,
        address[] memory defaultOperators_
    ) {
        _name = name_;
        _symbol = symbol_;

        _defaultOperatorsArray = defaultOperators_;
        for (uint256 i = 0; i < defaultOperators_.length; i++) {
            _defaultOperators[defaultOperators_[i]] = true;
        }

        // register interfaces
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
    }

    /**
     * @dev See {IERC777-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC777-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {ERC20-decimals}.
     *
     * Always returns 18, as per the
     * [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
     */
    function decimals() public pure virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC777-granularity}.
     *
     * This implementation always returns `1`.
     */
    function granularity() public view virtual override returns (uint256) {
        return 1;
    }

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

    /**
     * @dev Returns the amount of tokens owned by an account (`tokenHolder`).
     */
    function balanceOf(address tokenHolder) public view virtual override(IERC20, IERC777) returns (uint256) {
        return _balances[tokenHolder];
    }

    /**
     * @dev See {IERC777-send}.
     *
     * Also emits a {IERC20-Transfer} event for ERC20 compatibility.
     */
    function send(
        address recipient,
        uint256 amount,
        bytes memory data
    ) public virtual override {
        _send(_msgSender(), recipient, amount, data, "", true);
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Unlike `send`, `recipient` is _not_ required to implement the {IERC777Recipient}
     * interface if it is a contract.
     *
     * Also emits a {Sent} event.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _send(_msgSender(), recipient, amount, "", "", false);
        return true;
    }

    /**
     * @dev See {IERC777-burn}.
     *
     * Also emits a {IERC20-Transfer} event for ERC20 compatibility.
     */
    function burn(uint256 amount, bytes memory data) public virtual override {
        _burn(_msgSender(), amount, data, "");
    }

    /**
     * @dev See {IERC777-isOperatorFor}.
     */
    function isOperatorFor(address operator, address tokenHolder) public view virtual override returns (bool) {
        return
            operator == tokenHolder ||
            (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
            _operators[tokenHolder][operator];
    }

    /**
     * @dev See {IERC777-authorizeOperator}.
     */
    function authorizeOperator(address operator) public virtual override {
        require(_msgSender() != operator, "ERC777: authorizing self as operator");

        if (_defaultOperators[operator]) {
            delete _revokedDefaultOperators[_msgSender()][operator];
        } else {
            _operators[_msgSender()][operator] = true;
        }

        emit AuthorizedOperator(operator, _msgSender());
    }

    /**
     * @dev See {IERC777-revokeOperator}.
     */
    function revokeOperator(address operator) public virtual override {
        require(operator != _msgSender(), "ERC777: revoking self as operator");

        if (_defaultOperators[operator]) {
            _revokedDefaultOperators[_msgSender()][operator] = true;
        } else {
            delete _operators[_msgSender()][operator];
        }

        emit RevokedOperator(operator, _msgSender());
    }

    /**
     * @dev See {IERC777-defaultOperators}.
     */
    function defaultOperators() public view virtual override returns (address[] memory) {
        return _defaultOperatorsArray;
    }

    /**
     * @dev See {IERC777-operatorSend}.
     *
     * Emits {Sent} and {IERC20-Transfer} events.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    ) public virtual override {
        require(isOperatorFor(_msgSender(), sender), "ERC777: caller is not an operator for holder");
        _send(sender, recipient, amount, data, operatorData, true);
    }

    /**
     * @dev See {IERC777-operatorBurn}.
     *
     * Emits {Burned} and {IERC20-Transfer} events.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    ) public virtual override {
        require(isOperatorFor(_msgSender(), account), "ERC777: caller is not an operator for holder");
        _burn(account, amount, data, operatorData);
    }

    /**
     * @dev See {IERC20-allowance}.
     *
     * Note that operator and allowance concepts are orthogonal: operators may
     * not have allowance, and accounts with allowance may not be operators
     * themselves.
     */
    function allowance(address holder, address spender) public view virtual override returns (uint256) {
        return _allowances[holder][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Note that accounts cannot have allowance issued by their operators.
     */
    function approve(address spender, uint256 value) public virtual override returns (bool) {
        address holder = _msgSender();
        _approve(holder, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Note that operator and allowance concepts are orthogonal: operators cannot
     * call `transferFrom` (unless they have allowance), and accounts with
     * allowance cannot call `operatorSend` (unless they are operators).
     *
     * Emits {Sent}, {IERC20-Transfer} and {IERC20-Approval} events.
     */
    function transferFrom(
        address holder,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(holder, spender, amount);
        _send(holder, recipient, amount, "", "", false);
        return true;
    }

    /**
     * @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with the caller address as the `operator` and with
     * `userData` and `operatorData`.
     *
     * See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits {Minted} and {IERC20-Transfer} events.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - if `account` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function _mint(
        address account,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    ) internal virtual {
        _mint(account, amount, userData, operatorData, true);
    }

    /**
     * @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * If `requireReceptionAck` is set to true, and if a send hook is
     * registered for `account`, the corresponding function will be called with
     * `operator`, `data` and `operatorData`.
     *
     * See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits {Minted} and {IERC20-Transfer} events.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - if `account` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function _mint(
        address account,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    ) internal virtual {
        require(account != address(0), "ERC777: mint to the zero address");

        address operator = _msgSender();

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

        // Update state variables
        _totalSupply += amount;
        _balances[account] += amount;

        _callTokensReceived(operator, address(0), account, amount, userData, operatorData, requireReceptionAck);

        emit Minted(operator, account, amount, userData, operatorData);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Send tokens
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _send(
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    ) internal virtual {
        require(from != address(0), "ERC777: transfer from the zero address");
        require(to != address(0), "ERC777: transfer to the zero address");

        address operator = _msgSender();

        _callTokensToSend(operator, from, to, amount, userData, operatorData);

        _move(operator, from, to, amount, userData, operatorData);

        _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);
    }

    /**
     * @dev Burn tokens
     * @param from address token holder address
     * @param amount uint256 amount of tokens to burn
     * @param data bytes extra information provided by the token holder
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _burn(
        address from,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    ) internal virtual {
        require(from != address(0), "ERC777: burn from the zero address");

        address operator = _msgSender();

        _callTokensToSend(operator, from, address(0), amount, data, operatorData);

        _beforeTokenTransfer(operator, from, address(0), amount);

        // Update state variables
        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC777: burn amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _totalSupply -= amount;

        emit Burned(operator, from, amount, data, operatorData);
        emit Transfer(from, address(0), amount);
    }

    function _move(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    ) private {
        _beforeTokenTransfer(operator, from, to, amount);

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

        emit Sent(operator, from, to, amount, userData, operatorData);
        emit Transfer(from, to, amount);
    }

    /**
     * @dev See {ERC20-_approve}.
     *
     * Note that accounts cannot have allowance issued by their operators.
     */
    function _approve(
        address holder,
        address spender,
        uint256 value
    ) internal virtual {
        require(holder != address(0), "ERC777: approve from the zero address");
        require(spender != address(0), "ERC777: approve to the zero address");

        _allowances[holder][spender] = value;
        emit Approval(holder, spender, value);
    }

    /**
     * @dev Call from.tokensToSend() if the interface is registered
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _callTokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    ) private {
        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(from, _TOKENS_SENDER_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
        }
    }

    /**
     * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
     * tokensReceived() was not registered for the recipient
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _callTokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    ) private {
        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(to, _TOKENS_RECIPIENT_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
        } else if (requireReceptionAck) {
            require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
        }
    }

    /**
     * @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, "ERC777: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes
     * calls to {send}, {transfer}, {operatorSend}, minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to 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 operator,
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

// File: contracts/MatchiToken.sol


pragma solidity ^0.8.4;





contract MatchiToken is ERC777, Pausable, AccessControl, Votes {
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    uint256 private immutable _cap;

    constructor(uint256 capacity, address[] memory defaultOperators)
        ERC777("Matchi Token", "MCH", defaultOperators) EIP712("MatchiToken", "1")
    {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(PAUSER_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
        _cap = capacity * 10**decimals();
    }

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

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

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

    function cap() public view virtual returns (uint256) {
        return _cap;
    }

    function _mint(
        address account,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    ) internal virtual override {
        require(
            ERC777.totalSupply() + amount <= cap(),
            "MatchiToken: cap exceeded"
        );
        super._mint(account, amount, userData, operatorData);
        _transferVotingUnits(address(0), account, amount);
    }

    function _burn(
        address from,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    ) internal virtual override {
        super._burn(from, amount, data, operatorData);
        _transferVotingUnits(from, address(0), amount);
    }

    function _send(
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    ) internal virtual override {
        super._send(from, to, amount, userData, operatorData, requireReceptionAck);
        _transferVotingUnits(from, to, amount);
    }

    function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
        _mint(to, amount, "", "");
    }

    function _getVotingUnits(address tokenHolder)
        internal
        view
        virtual
        override
        returns (uint256)
    {
        return balanceOf(tokenHolder);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"capacity","type":"uint256"},{"internalType":"address[]","name":"defaultOperators","type":"address[]"}],"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":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"AuthorizedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"RevokedOperator","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":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Sent","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":[{"internalType":"address","name":"holder","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":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"authorizeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenHolder","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"defaultOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","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":"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":[],"name":"granularity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"operator","type":"address"},{"internalType":"address","name":"tokenHolder","type":"address"}],"name":"isOperatorFor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"operatorBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"operatorSend","outputs":[],"stateMutability":"nonpayable","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":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"revokeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"send","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":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101606040523480156200001257600080fd5b50604051620068de380380620068de83398181016040528101906200003891906200088f565b6040518060400160405280600b81526020017f4d6174636869546f6b656e0000000000000000000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600c81526020017f4d617463686920546f6b656e00000000000000000000000000000000000000008152506040518060400160405280600381526020017f4d434800000000000000000000000000000000000000000000000000000000008152508482600290805190602001906200012992919062000674565b5081600390805190602001906200014292919062000674565b5080600490805190602001906200015b92919062000705565b5060005b8151811015620001f45760016005600084848151811062000185576200018462000d80565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080620001eb9062000cd4565b9150506200015f565b50731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff166329965a1d307fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce2177054306040518463ffffffff1660e01b8152600401620002689392919062000928565b600060405180830381600087803b1580156200028357600080fd5b505af115801562000298573d6000803e3d6000fd5b50505050731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff166329965a1d307faea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a306040518463ffffffff1660e01b81526004016200030f9392919062000928565b600060405180830381600087803b1580156200032a57600080fd5b505af11580156200033f573d6000803e3d6000fd5b505050505050506000600960006101000a81548160ff02191690831515021790555060008280519060200120905060008280519060200120905060007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90508260e081815250508161010081815250504660a08181525050620003ca818484620004ca60201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1660601b8152505080610120818152505050505050506200042b6000801b336200050660201b60201c565b6200045d7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336200050660201b60201c565b6200048f7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200050660201b60201c565b6200049f620005f860201b60201c565b600a620004ad919062000a75565b82620004ba919062000bb2565b6101408181525050505062000e44565b60008383834630604051602001620004e795949392919062000965565b6040516020818303038152906040528051906020012090509392505050565b6200051882826200060160201b60201c565b620005f4576001600a600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620005996200066c60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006012905090565b6000600a600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600033905090565b828054620006829062000c68565b90600052602060002090601f016020900481019282620006a65760008555620006f2565b82601f10620006c157805160ff1916838001178555620006f2565b82800160010185558215620006f2579182015b82811115620006f1578251825591602001919060010190620006d4565b5b50905062000701919062000794565b5090565b82805482825590600052602060002090810192821562000781579160200282015b82811115620007805782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000726565b5b50905062000790919062000794565b5090565b5b80821115620007af57600081600090555060010162000795565b5090565b6000620007ca620007c484620009eb565b620009c2565b90508083825260208201905082856020860282011115620007f057620007ef62000de3565b5b60005b858110156200082457816200080988826200082e565b845260208401935060208301925050600181019050620007f3565b5050509392505050565b6000815190506200083f8162000e10565b92915050565b600082601f8301126200085d576200085c62000dde565b5b81516200086f848260208601620007b3565b91505092915050565b600081519050620008898162000e2a565b92915050565b60008060408385031215620008a957620008a862000ded565b5b6000620008b98582860162000878565b925050602083015167ffffffffffffffff811115620008dd57620008dc62000de8565b5b620008eb8582860162000845565b9150509250929050565b620009008162000c13565b82525050565b620009118162000c27565b82525050565b620009228162000c51565b82525050565b60006060820190506200093f6000830186620008f5565b6200094e602083018562000906565b6200095d6040830184620008f5565b949350505050565b600060a0820190506200097c600083018862000906565b6200098b602083018762000906565b6200099a604083018662000906565b620009a9606083018562000917565b620009b86080830184620008f5565b9695505050505050565b6000620009ce620009e1565b9050620009dc828262000c9e565b919050565b6000604051905090565b600067ffffffffffffffff82111562000a095762000a0862000daf565b5b602082029050602081019050919050565b6000808291508390505b600185111562000a6c5780860481111562000a445762000a4362000d22565b5b600185161562000a545780820291505b808102905062000a648562000e03565b945062000a24565b94509492505050565b600062000a828262000c51565b915062000a8f8362000c5b565b925062000abe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848462000ac6565b905092915050565b60008262000ad8576001905062000bab565b8162000ae8576000905062000bab565b816001811462000b01576002811462000b0c5762000b42565b600191505062000bab565b60ff84111562000b215762000b2062000d22565b5b8360020a91508482111562000b3b5762000b3a62000d22565b5b5062000bab565b5060208310610133831016604e8410600b841016171562000b7c5782820a90508381111562000b765762000b7562000d22565b5b62000bab565b62000b8b848484600162000a1a565b9250905081840481111562000ba55762000ba462000d22565b5b81810290505b9392505050565b600062000bbf8262000c51565b915062000bcc8362000c51565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000c085762000c0762000d22565b5b828202905092915050565b600062000c208262000c31565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000600282049050600182168062000c8157607f821691505b6020821081141562000c985762000c9762000d51565b5b50919050565b62000ca98262000df2565b810181811067ffffffffffffffff8211171562000ccb5762000cca62000daf565b5b80604052505050565b600062000ce18262000c51565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141562000d175762000d1662000d22565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160011c9050919050565b62000e1b8162000c13565b811462000e2757600080fd5b50565b62000e358162000c51565b811462000e4157600080fd5b50565b60805160a05160c05160601c60e051610100516101205161014051615a3c62000ea26000396000610a1f01526000611d2d01526000611d6f01526000611d4e01526000611c8301526000611cd901526000611d020152615a3c6000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c806370a082311161013b578063a9059cbb116100b8578063dd62ed3e1161007c578063dd62ed3e14610717578063e63ab1e914610747578063fad8b32a14610765578063fc673c4f14610781578063fe9d93031461079d57610248565b8063a9059cbb14610661578063c3cda52014610691578063d5391393146106ad578063d547741f146106cb578063d95b6371146106e757610248565b8063959b8c3f116100ff578063959b8c3f146105bd57806395d89b41146105d95780639ab24eb0146105f75780639bd9bbc614610627578063a217fddf1461064357610248565b806370a08231146104f35780637ecebe00146105235780638456cb59146105535780638e539e8c1461055d57806391d148541461058d57610248565b80633644e515116101c9578063556f0dc71161018d578063556f0dc71461044f578063587cde1e1461046d5780635c19a95c1461049d5780635c975abb146104b957806362ad1b83146104d757610248565b80633644e515146103bf57806336568abe146103dd5780633a46b1a8146103f95780633f4ba83a1461042957806340c10f191461043357610248565b806323b872dd1161021057806323b872dd14610307578063248a9ca3146103375780632f2ff15d14610367578063313ce56714610383578063355274ea146103a157610248565b806301ffc9a71461024d57806306e485381461027d57806306fdde031461029b578063095ea7b3146102b957806318160ddd146102e9575b600080fd5b61026760048036038101906102629190614070565b6107b9565b6040516102749190614833565b60405180910390f35b610285610833565b6040516102929190614811565b60405180910390f35b6102a36108c1565b6040516102b09190614946565b60405180910390f35b6102d360048036038101906102ce9190613e28565b610953565b6040516102e09190614833565b60405180910390f35b6102f1610976565b6040516102fe9190614ce8565b60405180910390f35b610321600480360381019061031c9190613d22565b610980565b60405161032e9190614833565b60405180910390f35b610351600480360381019061034c9190614003565b6109d1565b60405161035e919061484e565b60405180910390f35b610381600480360381019061037c9190614030565b6109f1565b005b61038b610a12565b6040516103989190614d71565b60405180910390f35b6103a9610a1b565b6040516103b69190614ce8565b60405180910390f35b6103c7610a43565b6040516103d4919061484e565b60405180910390f35b6103f760048036038101906103f29190614030565b610a52565b005b610413600480360381019061040e9190613e28565b610ad5565b6040516104209190614ce8565b60405180910390f35b610431610b30565b005b61044d60048036038101906104489190613e28565b610b65565b005b610457610bbe565b6040516104649190614ce8565b60405180910390f35b61048760048036038101906104829190613c88565b610bc7565b604051610494919061475e565b60405180910390f35b6104b760048036038101906104b29190613c88565b610c30565b005b6104c1610c4a565b6040516104ce9190614833565b60405180910390f35b6104f160048036038101906104ec9190613d75565b610c61565b005b61050d60048036038101906105089190613c88565b610cc7565b60405161051a9190614ce8565b60405180910390f35b61053d60048036038101906105389190613c88565b610d0f565b60405161054a9190614ce8565b60405180910390f35b61055b610d5f565b005b6105776004803603810190610572919061409d565b610d94565b6040516105849190614ce8565b60405180910390f35b6105a760048036038101906105a29190614030565b610df3565b6040516105b49190614833565b60405180910390f35b6105d760048036038101906105d29190613c88565b610e5e565b005b6105e16110bf565b6040516105ee9190614946565b60405180910390f35b610611600480360381019061060c9190613c88565b611151565b60405161061e9190614ce8565b60405180910390f35b610641600480360381019061063c9190613e68565b6111a1565b005b61064b6111cb565b604051610658919061484e565b60405180910390f35b61067b60048036038101906106769190613e28565b6111d2565b6040516106889190614833565b60405180910390f35b6106ab60048036038101906106a69190613f76565b611212565b005b6106b5611316565b6040516106c2919061484e565b60405180910390f35b6106e560048036038101906106e09190614030565b61133a565b005b61070160048036038101906106fc9190613ce2565b61135b565b60405161070e9190614833565b60405180910390f35b610731600480360381019061072c9190613ce2565b61150c565b60405161073e9190614ce8565b60405180910390f35b61074f611593565b60405161075c919061484e565b60405180910390f35b61077f600480360381019061077a9190613c88565b6115b7565b005b61079b60048036038101906107969190613ed7565b611818565b005b6107b760048036038101906107b291906140ca565b61187a565b005b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061082c575061082b826118a0565b5b9050919050565b606060048054806020026020016040519081016040528092919081815260200182805480156108b757602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161086d575b5050505050905090565b6060600280546108d09061506a565b80601f01602080910402602001604051908101604052809291908181526020018280546108fc9061506a565b80156109495780601f1061091e57610100808354040283529160200191610949565b820191906000526020600020905b81548152906001019060200180831161092c57829003601f168201915b5050505050905090565b60008061095e61190a565b905061096b818585611912565b600191505092915050565b6000600154905090565b60008061098b61190a565b9050610998858285611add565b6109c585858560405180602001604052806000815250604051806020016040528060008152506000611b69565b60019150509392505050565b6000600a6000838152602001908152602001600020600101549050919050565b6109fa826109d1565b610a0381611b8a565b610a0d8383611b9e565b505050565b60006012905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b6000610a4d611c7f565b905090565b610a5a61190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ac7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610abe90614cc8565b60405180910390fd5b610ad18282611d99565b5050565b6000610b2882600c60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611e7b90919063ffffffff16565b905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610b5a81611b8a565b610b62611fd3565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610b8f81611b8a565b610bb983836040518060200160405280600081525060405180602001604052806000815250612036565b505050565b60006001905090565b6000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610c3a61190a565b9050610c4681836120b0565b5050565b6000600960009054906101000a900460ff16905090565b610c72610c6c61190a565b8661135b565b610cb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca890614c48565b60405180910390fd5b610cc085858585856001611b69565b5050505050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000610d58600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206121c4565b9050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610d8981611b8a565b610d916121d2565b50565b6000438210610dd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dcf90614b68565b60405180910390fd5b610dec82600d611e7b90919063ffffffff16565b9050919050565b6000600a600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b8073ffffffffffffffffffffffffffffffffffffffff16610e7d61190a565b73ffffffffffffffffffffffffffffffffffffffff161415610ed4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ecb90614aa8565b60405180910390fd5b600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610fbe5760076000610f3261190a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905561105b565b600160066000610fcc61190a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b61106361190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f960405160405180910390a350565b6060600380546110ce9061506a565b80601f01602080910402602001604051908101604052809291908181526020018280546110fa9061506a565b80156111475780601f1061111c57610100808354040283529160200191611147565b820191906000526020600020905b81548152906001019060200180831161112a57829003601f168201915b5050505050905090565b600061119a600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612235565b9050919050565b6111c66111ac61190a565b848484604051806020016040528060008152506001611b69565b505050565b6000801b81565b60006112086111df61190a565b848460405180602001604052806000815250604051806020016040528060008152506000611b69565b6001905092915050565b83421115611255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124c90614b48565b60405180910390fd5b60006112b76112af7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8989896040516020016112949493929190614869565b604051602081830303815290604052805190602001206122d0565b8585856122ea565b90506112c281612315565b8614611303576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fa90614a08565b60405180910390fd5b61130d81886120b0565b50505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b611343826109d1565b61134c81611b8a565b6113568383611d99565b505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806114735750600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156114725750600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16155b5b806115045750600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b905092915050565b6000600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6115bf61190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561162d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162490614b08565b60405180910390fd5b600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156117205760016007600061168d61190a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506117b4565b6006600061172c61190a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff02191690555b6117bc61190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa160405160405180910390a350565b61182961182361190a565b8561135b565b611868576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185f90614c48565b60405180910390fd5b61187484848484612373565b50505050565b61189c61188561190a565b838360405180602001604052806000815250612373565b5050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611982576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611979906149e8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156119f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e990614ca8565b60405180910390fd5b80600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051611ad09190614ce8565b60405180910390a3505050565b6000611ae9848461150c565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611b635781811015611b55576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b4c90614a88565b60405180910390fd5b611b628484848403611912565b5b50505050565b611b77868686868686612391565b611b828686866124b1565b505050505050565b611b9b81611b9661190a565b612571565b50565b611ba88282610df3565b611c7b576001600a600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611c2061190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611cfb57507f000000000000000000000000000000000000000000000000000000000000000046145b15611d28577f00000000000000000000000000000000000000000000000000000000000000009050611d96565b611d937f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061260e565b90505b90565b611da38282610df3565b15611e77576000600a600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611e1c61190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000438210611ebf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eb690614ae8565b60405180910390fd5b60008360000180549050905060005b81811015611f43576000611ee28284612648565b905084866000018281548110611efb57611efa615193565b5b9060005260206000200160000160009054906101000a900463ffffffff1663ffffffff161115611f2d57809250611f3d565b600181611f3a9190614e5e565b91505b50611ece565b60008214611fa85784600001600183611f5c9190614f3f565b81548110611f6d57611f6c615193565b5b9060005260206000200160000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16611fab565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169250505092915050565b611fdb61266e565b6000600960006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61201f61190a565b60405161202c919061475e565b60405180910390a1565b61203e610a1b565b83612047610976565b6120519190614e5e565b1115612092576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612089906149a8565b60405180910390fd5b61209e848484846126b7565b6120aa600085856124b1565b50505050565b60006120bb83610bc7565b905081600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a46121bf81836121ba866126cb565b6126dd565b505050565b600081600001549050919050565b6121da6128ea565b6001600960006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861221e61190a565b60405161222b919061475e565b60405180910390a1565b60008082600001805490509050600081146122a7578260000160018261225b9190614f3f565b8154811061226c5761226b615193565b5b9060005260206000200160000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166122aa565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16915050919050565b60006122e36122dd611c7f565b83612934565b9050919050565b60008060006122fb87878787612967565b9150915061230881612a74565b8192505050949350505050565b600080600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050612362816121c4565b915061236d81612c49565b50919050565b61237f84848484612c5f565b61238b846000856124b1565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415612401576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123f890614c68565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415612471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246890614c08565b60405180910390fd5b600061247b61190a565b905061248b818888888888612eb2565b612499818888888888613028565b6124a881888888888888613242565b50505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612501576124fe61342382600d6134399092919063ffffffff16565b50505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156125515761254e61346782600d6134399092919063ffffffff16565b50505b61256c61255d84610bc7565b61256684610bc7565b836126dd565b505050565b61257b8282610df3565b61260a576125a08173ffffffffffffffffffffffffffffffffffffffff16601461347d565b6125ae8360001c602061347d565b6040516020016125bf929190614724565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126019190614946565b60405180910390fd5b5050565b600083838346306040516020016126299594939291906148ae565b6040516020818303038152906040528051906020012090509392505050565b600060028284186126599190614eb4565b8284166126669190614e5e565b905092915050565b612676610c4a565b6126b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126ac906149c8565b60405180910390fd5b565b6126c58484848460016136b9565b50505050565b60006126d682610cc7565b9050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156127195750600081115b156128e557600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612801576000806127aa61346784600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206134399092919063ffffffff16565b915091508473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516127f6929190614d48565b60405180910390a250505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146128e45760008061288d61342384600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206134399092919063ffffffff16565b915091508373ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516128d9929190614d48565b60405180910390a250505b5b505050565b6128f2610c4a565b15612932576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292990614b28565b60405180910390fd5b565b600082826040516020016129499291906146ed565b60405160208183030381529060405280519060200120905092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156129a2576000600391509150612a6b565b601b8560ff16141580156129ba5750601c8560ff1614155b156129cc576000600491509150612a6b565b6000600187878787604051600081526020016040526040516129f19493929190614901565b6020604051602081039080840390855afa158015612a13573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612a6257600060019250925050612a6b565b80600092509250505b94509492505050565b60006004811115612a8857612a87615135565b5b816004811115612a9b57612a9a615135565b5b1415612aa657612c46565b60016004811115612aba57612ab9615135565b5b816004811115612acd57612acc615135565b5b1415612b0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0590614968565b60405180910390fd5b60026004811115612b2257612b21615135565b5b816004811115612b3557612b34615135565b5b1415612b76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b6d90614a28565b60405180910390fd5b60036004811115612b8a57612b89615135565b5b816004811115612b9d57612b9c615135565b5b1415612bde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bd590614ac8565b60405180910390fd5b600480811115612bf157612bf0615135565b5b816004811115612c0457612c03615135565b5b1415612c45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c3c90614b88565b60405180910390fd5b5b50565b6001816000016000828254019250508190555050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612ccf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cc690614a68565b60405180910390fd5b6000612cd961190a565b9050612cea81866000878787612eb2565b612cf78186600087613897565b60008060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905084811015612d7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d7490614c88565b60405180910390fd5b8481036000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508460016000828254612dd49190614f3f565b925050819055508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a4098878787604051612e3c93929190614d03565b60405180910390a3600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef87604051612ea29190614ce8565b60405180910390a3505050505050565b6000731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff1663aabbb8ca877f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe8956040518363ffffffff1660e01b8152600401612f239291906147e8565b60206040518083038186803b158015612f3b57600080fd5b505afa158015612f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f739190613cb5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461301f578073ffffffffffffffffffffffffffffffffffffffff166375ab97828888888888886040518763ffffffff1660e01b8152600401612fec96959493929190614779565b600060405180830381600087803b15801561300657600080fd5b505af115801561301a573d6000803e3d6000fd5b505050505b50505050505050565b61303486868686613897565b60008060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050838110156130ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130b190614a48565b60405180910390fd5b8381036000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550836000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461314d9190614e5e565b925050819055508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc826146779878787876040516131cc93929190614d03565b60405180910390a48473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040516132319190614ce8565b60405180910390a350505050505050565b6000731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff1663aabbb8ca877fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6040518363ffffffff1660e01b81526004016132b39291906147e8565b60206040518083038186803b1580156132cb57600080fd5b505afa1580156132df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133039190613cb5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146133b2578073ffffffffffffffffffffffffffffffffffffffff166223de298989898989896040518763ffffffff1660e01b815260040161337b96959493929190614779565b600060405180830381600087803b15801561339557600080fd5b505af11580156133a9573d6000803e3d6000fd5b50505050613419565b8115613418576133d78673ffffffffffffffffffffffffffffffffffffffff166138b1565b15613417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161340e90614be8565b60405180910390fd5b5b5b5050505050505050565b600081836134319190614e5e565b905092915050565b60008061345b8561345661344c88612235565b868863ffffffff16565b6138d4565b91509150935093915050565b600081836134759190614f3f565b905092915050565b6060600060028360026134909190614ee5565b61349a9190614e5e565b67ffffffffffffffff8111156134b3576134b26151c2565b5b6040519080825280601f01601f1916602001820160405280156134e55781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061351d5761351c615193565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061358157613580615193565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026135c19190614ee5565b6135cb9190614e5e565b90505b600181111561366b577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061360d5761360c615193565b5b1a60f81b82828151811061362457613623615193565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c94508061366490615040565b90506135ce565b50600084146136af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136a690614988565b60405180910390fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415613729576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161372090614ba8565b60405180910390fd5b600061373361190a565b90506137428160008888613897565b84600160008282546137549190614e5e565b92505081905550846000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546137a99190614e5e565b925050819055506137c08160008888888888613242565b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d87878760405161382193929190614d03565b60405180910390a38573ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040516138879190614ce8565b60405180910390a3505050505050565b61389f6128ea565b6138ab84848484613ad6565b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008060008460000180549050905060006138ee86612235565b90506000821180156139445750438660000160018461390d9190614f3f565b8154811061391e5761391d615193565b5b9060005260206000200160000160009054906101000a900463ffffffff1663ffffffff16145b156139d45761395285613adc565b866000016001846139639190614f3f565b8154811061397457613973615193565b5b9060005260206000200160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550613ac7565b8560000160405180604001604052806139ec43613b47565b63ffffffff168152602001613a0088613adc565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555050505b80859350935050509250929050565b50505050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8016821115613b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b3690614bc8565b60405180910390fd5b819050919050565b600063ffffffff8016821115613b92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b8990614c28565b60405180910390fd5b819050919050565b6000613bad613ba884614db1565b614d8c565b905082815260208101848484011115613bc957613bc86151f6565b5b613bd4848285614ffe565b509392505050565b600081359050613beb81615993565b92915050565b600081519050613c0081615993565b92915050565b600081359050613c15816159aa565b92915050565b600081359050613c2a816159c1565b92915050565b600082601f830112613c4557613c446151f1565b5b8135613c55848260208601613b9a565b91505092915050565b600081359050613c6d816159d8565b92915050565b600081359050613c82816159ef565b92915050565b600060208284031215613c9e57613c9d615200565b5b6000613cac84828501613bdc565b91505092915050565b600060208284031215613ccb57613cca615200565b5b6000613cd984828501613bf1565b91505092915050565b60008060408385031215613cf957613cf8615200565b5b6000613d0785828601613bdc565b9250506020613d1885828601613bdc565b9150509250929050565b600080600060608486031215613d3b57613d3a615200565b5b6000613d4986828701613bdc565b9350506020613d5a86828701613bdc565b9250506040613d6b86828701613c5e565b9150509250925092565b600080600080600060a08688031215613d9157613d90615200565b5b6000613d9f88828901613bdc565b9550506020613db088828901613bdc565b9450506040613dc188828901613c5e565b935050606086013567ffffffffffffffff811115613de257613de16151fb565b5b613dee88828901613c30565b925050608086013567ffffffffffffffff811115613e0f57613e0e6151fb565b5b613e1b88828901613c30565b9150509295509295909350565b60008060408385031215613e3f57613e3e615200565b5b6000613e4d85828601613bdc565b9250506020613e5e85828601613c5e565b9150509250929050565b600080600060608486031215613e8157613e80615200565b5b6000613e8f86828701613bdc565b9350506020613ea086828701613c5e565b925050604084013567ffffffffffffffff811115613ec157613ec06151fb565b5b613ecd86828701613c30565b9150509250925092565b60008060008060808587031215613ef157613ef0615200565b5b6000613eff87828801613bdc565b9450506020613f1087828801613c5e565b935050604085013567ffffffffffffffff811115613f3157613f306151fb565b5b613f3d87828801613c30565b925050606085013567ffffffffffffffff811115613f5e57613f5d6151fb565b5b613f6a87828801613c30565b91505092959194509250565b60008060008060008060c08789031215613f9357613f92615200565b5b6000613fa189828a01613bdc565b9650506020613fb289828a01613c5e565b9550506040613fc389828a01613c5e565b9450506060613fd489828a01613c73565b9350506080613fe589828a01613c06565b92505060a0613ff689828a01613c06565b9150509295509295509295565b60006020828403121561401957614018615200565b5b600061402784828501613c06565b91505092915050565b6000806040838503121561404757614046615200565b5b600061405585828601613c06565b925050602061406685828601613bdc565b9150509250929050565b60006020828403121561408657614085615200565b5b600061409484828501613c1b565b91505092915050565b6000602082840312156140b3576140b2615200565b5b60006140c184828501613c5e565b91505092915050565b600080604083850312156140e1576140e0615200565b5b60006140ef85828601613c5e565b925050602083013567ffffffffffffffff8111156141105761410f6151fb565b5b61411c85828601613c30565b9150509250929050565b6000614132838361413e565b60208301905092915050565b61414781614f73565b82525050565b61415681614f73565b82525050565b600061416782614df2565b6141718185614e20565b935061417c83614de2565b8060005b838110156141ad5781516141948882614126565b975061419f83614e13565b925050600181019050614180565b5085935050505092915050565b6141c381614f85565b82525050565b6141d281614f91565b82525050565b6141e96141e482614f91565b6150cd565b82525050565b60006141fa82614dfd565b6142048185614e31565b935061421481856020860161500d565b61421d81615205565b840191505092915050565b600061423382614e08565b61423d8185614e42565b935061424d81856020860161500d565b61425681615205565b840191505092915050565b600061426c82614e08565b6142768185614e53565b935061428681856020860161500d565b80840191505092915050565b600061429f601883614e42565b91506142aa82615216565b602082019050919050565b60006142c2602083614e42565b91506142cd8261523f565b602082019050919050565b60006142e5601983614e42565b91506142f082615268565b602082019050919050565b6000614308601483614e42565b915061431382615291565b602082019050919050565b600061432b602583614e42565b9150614336826152ba565b604082019050919050565b600061434e601483614e42565b915061435982615309565b602082019050919050565b6000614371601f83614e42565b915061437c82615332565b602082019050919050565b6000614394602783614e42565b915061439f8261535b565b604082019050919050565b60006143b7600283614e53565b91506143c2826153aa565b600282019050919050565b60006143da602283614e42565b91506143e5826153d3565b604082019050919050565b60006143fd601e83614e42565b915061440882615422565b602082019050919050565b6000614420602483614e42565b915061442b8261544b565b604082019050919050565b6000614443602283614e42565b915061444e8261549a565b604082019050919050565b6000614466602083614e42565b9150614471826154e9565b602082019050919050565b6000614489602183614e42565b915061449482615512565b604082019050919050565b60006144ac601083614e42565b91506144b782615561565b602082019050919050565b60006144cf601883614e42565b91506144da8261558a565b602082019050919050565b60006144f2601a83614e42565b91506144fd826155b3565b602082019050919050565b6000614515602283614e42565b9150614520826155dc565b604082019050919050565b6000614538602083614e42565b91506145438261562b565b602082019050919050565b600061455b602783614e42565b915061456682615654565b604082019050919050565b600061457e604d83614e42565b9150614589826156a3565b606082019050919050565b60006145a1602483614e42565b91506145ac82615718565b604082019050919050565b60006145c4602683614e42565b91506145cf82615767565b604082019050919050565b60006145e7602c83614e42565b91506145f2826157b6565b604082019050919050565b600061460a601783614e53565b915061461582615805565b601782019050919050565b600061462d602683614e42565b91506146388261582e565b604082019050919050565b6000614650602383614e42565b915061465b8261587d565b604082019050919050565b6000614673602383614e42565b915061467e826158cc565b604082019050919050565b6000614696601183614e53565b91506146a18261591b565b601182019050919050565b60006146b9602f83614e42565b91506146c482615944565b604082019050919050565b6146d881614fe7565b82525050565b6146e781614ff1565b82525050565b60006146f8826143aa565b915061470482856141d8565b60208201915061471482846141d8565b6020820191508190509392505050565b600061472f826145fd565b915061473b8285614261565b915061474682614689565b91506147528284614261565b91508190509392505050565b6000602082019050614773600083018461414d565b92915050565b600060c08201905061478e600083018961414d565b61479b602083018861414d565b6147a8604083018761414d565b6147b560608301866146cf565b81810360808301526147c781856141ef565b905081810360a08301526147db81846141ef565b9050979650505050505050565b60006040820190506147fd600083018561414d565b61480a60208301846141c9565b9392505050565b6000602082019050818103600083015261482b818461415c565b905092915050565b600060208201905061484860008301846141ba565b92915050565b600060208201905061486360008301846141c9565b92915050565b600060808201905061487e60008301876141c9565b61488b602083018661414d565b61489860408301856146cf565b6148a560608301846146cf565b95945050505050565b600060a0820190506148c360008301886141c9565b6148d060208301876141c9565b6148dd60408301866141c9565b6148ea60608301856146cf565b6148f7608083018461414d565b9695505050505050565b600060808201905061491660008301876141c9565b61492360208301866146de565b61493060408301856141c9565b61493d60608301846141c9565b95945050505050565b600060208201905081810360008301526149608184614228565b905092915050565b6000602082019050818103600083015261498181614292565b9050919050565b600060208201905081810360008301526149a1816142b5565b9050919050565b600060208201905081810360008301526149c1816142d8565b9050919050565b600060208201905081810360008301526149e1816142fb565b9050919050565b60006020820190508181036000830152614a018161431e565b9050919050565b60006020820190508181036000830152614a2181614341565b9050919050565b60006020820190508181036000830152614a4181614364565b9050919050565b60006020820190508181036000830152614a6181614387565b9050919050565b60006020820190508181036000830152614a81816143cd565b9050919050565b60006020820190508181036000830152614aa1816143f0565b9050919050565b60006020820190508181036000830152614ac181614413565b9050919050565b60006020820190508181036000830152614ae181614436565b9050919050565b60006020820190508181036000830152614b0181614459565b9050919050565b60006020820190508181036000830152614b218161447c565b9050919050565b60006020820190508181036000830152614b418161449f565b9050919050565b60006020820190508181036000830152614b61816144c2565b9050919050565b60006020820190508181036000830152614b81816144e5565b9050919050565b60006020820190508181036000830152614ba181614508565b9050919050565b60006020820190508181036000830152614bc18161452b565b9050919050565b60006020820190508181036000830152614be18161454e565b9050919050565b60006020820190508181036000830152614c0181614571565b9050919050565b60006020820190508181036000830152614c2181614594565b9050919050565b60006020820190508181036000830152614c41816145b7565b9050919050565b60006020820190508181036000830152614c61816145da565b9050919050565b60006020820190508181036000830152614c8181614620565b9050919050565b60006020820190508181036000830152614ca181614643565b9050919050565b60006020820190508181036000830152614cc181614666565b9050919050565b60006020820190508181036000830152614ce1816146ac565b9050919050565b6000602082019050614cfd60008301846146cf565b92915050565b6000606082019050614d1860008301866146cf565b8181036020830152614d2a81856141ef565b90508181036040830152614d3e81846141ef565b9050949350505050565b6000604082019050614d5d60008301856146cf565b614d6a60208301846146cf565b9392505050565b6000602082019050614d8660008301846146de565b92915050565b6000614d96614da7565b9050614da2828261509c565b919050565b6000604051905090565b600067ffffffffffffffff821115614dcc57614dcb6151c2565b5b614dd582615205565b9050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b6000614e6982614fe7565b9150614e7483614fe7565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614ea957614ea86150d7565b5b828201905092915050565b6000614ebf82614fe7565b9150614eca83614fe7565b925082614eda57614ed9615106565b5b828204905092915050565b6000614ef082614fe7565b9150614efb83614fe7565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614f3457614f336150d7565b5b828202905092915050565b6000614f4a82614fe7565b9150614f5583614fe7565b925082821015614f6857614f676150d7565b5b828203905092915050565b6000614f7e82614fc7565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b8381101561502b578082015181840152602081019050615010565b8381111561503a576000848401525b50505050565b600061504b82614fe7565b9150600082141561505f5761505e6150d7565b5b600182039050919050565b6000600282049050600182168061508257607f821691505b6020821081141561509657615095615164565b5b50919050565b6150a582615205565b810181811067ffffffffffffffff821117156150c4576150c36151c2565b5b80604052505050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b7f4d6174636869546f6b656e3a2063617020657863656564656400000000000000600082015250565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b7f4552433737373a20617070726f76652066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f566f7465733a20696e76616c6964206e6f6e6365000000000000000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b7f4552433737373a207472616e7366657220616d6f756e7420657863656564732060008201527f62616c616e636500000000000000000000000000000000000000000000000000602082015250565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433737373a206275726e2066726f6d20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a20696e73756666696369656e7420616c6c6f77616e63650000600082015250565b7f4552433737373a20617574686f72697a696e672073656c66206173206f70657260008201527f61746f7200000000000000000000000000000000000000000000000000000000602082015250565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f436865636b706f696e74733a20626c6f636b206e6f7420796574206d696e6564600082015250565b7f4552433737373a207265766f6b696e672073656c66206173206f70657261746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b7f566f7465733a207369676e617475726520657870697265640000000000000000600082015250565b7f566f7465733a20626c6f636b206e6f7420796574206d696e6564000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203260008201527f3234206269747300000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a20746f6b656e20726563697069656e7420636f6e747261637460008201527f20686173206e6f20696d706c656d656e74657220666f7220455243373737546f60208201527f6b656e73526563697069656e7400000000000000000000000000000000000000604082015250565b7f4552433737373a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203360008201527f3220626974730000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a2063616c6c6572206973206e6f7420616e206f70657261746f60008201527f7220666f7220686f6c6465720000000000000000000000000000000000000000602082015250565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b7f4552433737373a207472616e736665722066726f6d20746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a206275726e20616d6f756e7420657863656564732062616c6160008201527f6e63650000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a20617070726f766520746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b61599c81614f73565b81146159a757600080fd5b50565b6159b381614f91565b81146159be57600080fd5b50565b6159ca81614f9b565b81146159d557600080fd5b50565b6159e181614fe7565b81146159ec57600080fd5b50565b6159f881614ff1565b8114615a0357600080fd5b5056fea264697066735822122023836b8516fd7aad97d60b9e3b1f005bf632f16bb28d0a2fdf5ea7be98822dfc64736f6c63430008070033000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102485760003560e01c806370a082311161013b578063a9059cbb116100b8578063dd62ed3e1161007c578063dd62ed3e14610717578063e63ab1e914610747578063fad8b32a14610765578063fc673c4f14610781578063fe9d93031461079d57610248565b8063a9059cbb14610661578063c3cda52014610691578063d5391393146106ad578063d547741f146106cb578063d95b6371146106e757610248565b8063959b8c3f116100ff578063959b8c3f146105bd57806395d89b41146105d95780639ab24eb0146105f75780639bd9bbc614610627578063a217fddf1461064357610248565b806370a08231146104f35780637ecebe00146105235780638456cb59146105535780638e539e8c1461055d57806391d148541461058d57610248565b80633644e515116101c9578063556f0dc71161018d578063556f0dc71461044f578063587cde1e1461046d5780635c19a95c1461049d5780635c975abb146104b957806362ad1b83146104d757610248565b80633644e515146103bf57806336568abe146103dd5780633a46b1a8146103f95780633f4ba83a1461042957806340c10f191461043357610248565b806323b872dd1161021057806323b872dd14610307578063248a9ca3146103375780632f2ff15d14610367578063313ce56714610383578063355274ea146103a157610248565b806301ffc9a71461024d57806306e485381461027d57806306fdde031461029b578063095ea7b3146102b957806318160ddd146102e9575b600080fd5b61026760048036038101906102629190614070565b6107b9565b6040516102749190614833565b60405180910390f35b610285610833565b6040516102929190614811565b60405180910390f35b6102a36108c1565b6040516102b09190614946565b60405180910390f35b6102d360048036038101906102ce9190613e28565b610953565b6040516102e09190614833565b60405180910390f35b6102f1610976565b6040516102fe9190614ce8565b60405180910390f35b610321600480360381019061031c9190613d22565b610980565b60405161032e9190614833565b60405180910390f35b610351600480360381019061034c9190614003565b6109d1565b60405161035e919061484e565b60405180910390f35b610381600480360381019061037c9190614030565b6109f1565b005b61038b610a12565b6040516103989190614d71565b60405180910390f35b6103a9610a1b565b6040516103b69190614ce8565b60405180910390f35b6103c7610a43565b6040516103d4919061484e565b60405180910390f35b6103f760048036038101906103f29190614030565b610a52565b005b610413600480360381019061040e9190613e28565b610ad5565b6040516104209190614ce8565b60405180910390f35b610431610b30565b005b61044d60048036038101906104489190613e28565b610b65565b005b610457610bbe565b6040516104649190614ce8565b60405180910390f35b61048760048036038101906104829190613c88565b610bc7565b604051610494919061475e565b60405180910390f35b6104b760048036038101906104b29190613c88565b610c30565b005b6104c1610c4a565b6040516104ce9190614833565b60405180910390f35b6104f160048036038101906104ec9190613d75565b610c61565b005b61050d60048036038101906105089190613c88565b610cc7565b60405161051a9190614ce8565b60405180910390f35b61053d60048036038101906105389190613c88565b610d0f565b60405161054a9190614ce8565b60405180910390f35b61055b610d5f565b005b6105776004803603810190610572919061409d565b610d94565b6040516105849190614ce8565b60405180910390f35b6105a760048036038101906105a29190614030565b610df3565b6040516105b49190614833565b60405180910390f35b6105d760048036038101906105d29190613c88565b610e5e565b005b6105e16110bf565b6040516105ee9190614946565b60405180910390f35b610611600480360381019061060c9190613c88565b611151565b60405161061e9190614ce8565b60405180910390f35b610641600480360381019061063c9190613e68565b6111a1565b005b61064b6111cb565b604051610658919061484e565b60405180910390f35b61067b60048036038101906106769190613e28565b6111d2565b6040516106889190614833565b60405180910390f35b6106ab60048036038101906106a69190613f76565b611212565b005b6106b5611316565b6040516106c2919061484e565b60405180910390f35b6106e560048036038101906106e09190614030565b61133a565b005b61070160048036038101906106fc9190613ce2565b61135b565b60405161070e9190614833565b60405180910390f35b610731600480360381019061072c9190613ce2565b61150c565b60405161073e9190614ce8565b60405180910390f35b61074f611593565b60405161075c919061484e565b60405180910390f35b61077f600480360381019061077a9190613c88565b6115b7565b005b61079b60048036038101906107969190613ed7565b611818565b005b6107b760048036038101906107b291906140ca565b61187a565b005b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061082c575061082b826118a0565b5b9050919050565b606060048054806020026020016040519081016040528092919081815260200182805480156108b757602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161086d575b5050505050905090565b6060600280546108d09061506a565b80601f01602080910402602001604051908101604052809291908181526020018280546108fc9061506a565b80156109495780601f1061091e57610100808354040283529160200191610949565b820191906000526020600020905b81548152906001019060200180831161092c57829003601f168201915b5050505050905090565b60008061095e61190a565b905061096b818585611912565b600191505092915050565b6000600154905090565b60008061098b61190a565b9050610998858285611add565b6109c585858560405180602001604052806000815250604051806020016040528060008152506000611b69565b60019150509392505050565b6000600a6000838152602001908152602001600020600101549050919050565b6109fa826109d1565b610a0381611b8a565b610a0d8383611b9e565b505050565b60006012905090565b60007f0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000905090565b6000610a4d611c7f565b905090565b610a5a61190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ac7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610abe90614cc8565b60405180910390fd5b610ad18282611d99565b5050565b6000610b2882600c60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611e7b90919063ffffffff16565b905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610b5a81611b8a565b610b62611fd3565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610b8f81611b8a565b610bb983836040518060200160405280600081525060405180602001604052806000815250612036565b505050565b60006001905090565b6000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610c3a61190a565b9050610c4681836120b0565b5050565b6000600960009054906101000a900460ff16905090565b610c72610c6c61190a565b8661135b565b610cb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca890614c48565b60405180910390fd5b610cc085858585856001611b69565b5050505050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000610d58600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206121c4565b9050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610d8981611b8a565b610d916121d2565b50565b6000438210610dd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dcf90614b68565b60405180910390fd5b610dec82600d611e7b90919063ffffffff16565b9050919050565b6000600a600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b8073ffffffffffffffffffffffffffffffffffffffff16610e7d61190a565b73ffffffffffffffffffffffffffffffffffffffff161415610ed4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ecb90614aa8565b60405180910390fd5b600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610fbe5760076000610f3261190a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905561105b565b600160066000610fcc61190a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b61106361190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f960405160405180910390a350565b6060600380546110ce9061506a565b80601f01602080910402602001604051908101604052809291908181526020018280546110fa9061506a565b80156111475780601f1061111c57610100808354040283529160200191611147565b820191906000526020600020905b81548152906001019060200180831161112a57829003601f168201915b5050505050905090565b600061119a600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612235565b9050919050565b6111c66111ac61190a565b848484604051806020016040528060008152506001611b69565b505050565b6000801b81565b60006112086111df61190a565b848460405180602001604052806000815250604051806020016040528060008152506000611b69565b6001905092915050565b83421115611255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124c90614b48565b60405180910390fd5b60006112b76112af7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8989896040516020016112949493929190614869565b604051602081830303815290604052805190602001206122d0565b8585856122ea565b90506112c281612315565b8614611303576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fa90614a08565b60405180910390fd5b61130d81886120b0565b50505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b611343826109d1565b61134c81611b8a565b6113568383611d99565b505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806114735750600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156114725750600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16155b5b806115045750600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b905092915050565b6000600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6115bf61190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561162d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162490614b08565b60405180910390fd5b600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156117205760016007600061168d61190a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506117b4565b6006600061172c61190a565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff02191690555b6117bc61190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa160405160405180910390a350565b61182961182361190a565b8561135b565b611868576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185f90614c48565b60405180910390fd5b61187484848484612373565b50505050565b61189c61188561190a565b838360405180602001604052806000815250612373565b5050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611982576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611979906149e8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156119f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e990614ca8565b60405180910390fd5b80600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051611ad09190614ce8565b60405180910390a3505050565b6000611ae9848461150c565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611b635781811015611b55576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b4c90614a88565b60405180910390fd5b611b628484848403611912565b5b50505050565b611b77868686868686612391565b611b828686866124b1565b505050505050565b611b9b81611b9661190a565b612571565b50565b611ba88282610df3565b611c7b576001600a600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611c2061190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60007f000000000000000000000000c132822fe97225a868ac2efed71532107e36e2ad73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611cfb57507f000000000000000000000000000000000000000000000000000000000000000146145b15611d28577fe7ca9653abf53cb3f16611cce5bb80f5cab9e27b683bc27ebc4ba8c2978530129050611d96565b611d937f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f7f120e13c5c368a367ed3637b32a2e117b7d5586bd68f8f4fcef5d5118678d0a7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc661260e565b90505b90565b611da38282610df3565b15611e77576000600a600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611e1c61190a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b6000438210611ebf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eb690614ae8565b60405180910390fd5b60008360000180549050905060005b81811015611f43576000611ee28284612648565b905084866000018281548110611efb57611efa615193565b5b9060005260206000200160000160009054906101000a900463ffffffff1663ffffffff161115611f2d57809250611f3d565b600181611f3a9190614e5e565b91505b50611ece565b60008214611fa85784600001600183611f5c9190614f3f565b81548110611f6d57611f6c615193565b5b9060005260206000200160000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16611fab565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169250505092915050565b611fdb61266e565b6000600960006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61201f61190a565b60405161202c919061475e565b60405180910390a1565b61203e610a1b565b83612047610976565b6120519190614e5e565b1115612092576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612089906149a8565b60405180910390fd5b61209e848484846126b7565b6120aa600085856124b1565b50505050565b60006120bb83610bc7565b905081600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a46121bf81836121ba866126cb565b6126dd565b505050565b600081600001549050919050565b6121da6128ea565b6001600960006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861221e61190a565b60405161222b919061475e565b60405180910390a1565b60008082600001805490509050600081146122a7578260000160018261225b9190614f3f565b8154811061226c5761226b615193565b5b9060005260206000200160000160049054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166122aa565b60005b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16915050919050565b60006122e36122dd611c7f565b83612934565b9050919050565b60008060006122fb87878787612967565b9150915061230881612a74565b8192505050949350505050565b600080600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050612362816121c4565b915061236d81612c49565b50919050565b61237f84848484612c5f565b61238b846000856124b1565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415612401576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123f890614c68565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415612471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246890614c08565b60405180910390fd5b600061247b61190a565b905061248b818888888888612eb2565b612499818888888888613028565b6124a881888888888888613242565b50505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612501576124fe61342382600d6134399092919063ffffffff16565b50505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156125515761254e61346782600d6134399092919063ffffffff16565b50505b61256c61255d84610bc7565b61256684610bc7565b836126dd565b505050565b61257b8282610df3565b61260a576125a08173ffffffffffffffffffffffffffffffffffffffff16601461347d565b6125ae8360001c602061347d565b6040516020016125bf929190614724565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126019190614946565b60405180910390fd5b5050565b600083838346306040516020016126299594939291906148ae565b6040516020818303038152906040528051906020012090509392505050565b600060028284186126599190614eb4565b8284166126669190614e5e565b905092915050565b612676610c4a565b6126b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126ac906149c8565b60405180910390fd5b565b6126c58484848460016136b9565b50505050565b60006126d682610cc7565b9050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156127195750600081115b156128e557600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612801576000806127aa61346784600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206134399092919063ffffffff16565b915091508473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516127f6929190614d48565b60405180910390a250505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146128e45760008061288d61342384600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206134399092919063ffffffff16565b915091508373ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516128d9929190614d48565b60405180910390a250505b5b505050565b6128f2610c4a565b15612932576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292990614b28565b60405180910390fd5b565b600082826040516020016129499291906146ed565b60405160208183030381529060405280519060200120905092915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156129a2576000600391509150612a6b565b601b8560ff16141580156129ba5750601c8560ff1614155b156129cc576000600491509150612a6b565b6000600187878787604051600081526020016040526040516129f19493929190614901565b6020604051602081039080840390855afa158015612a13573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612a6257600060019250925050612a6b565b80600092509250505b94509492505050565b60006004811115612a8857612a87615135565b5b816004811115612a9b57612a9a615135565b5b1415612aa657612c46565b60016004811115612aba57612ab9615135565b5b816004811115612acd57612acc615135565b5b1415612b0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0590614968565b60405180910390fd5b60026004811115612b2257612b21615135565b5b816004811115612b3557612b34615135565b5b1415612b76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b6d90614a28565b60405180910390fd5b60036004811115612b8a57612b89615135565b5b816004811115612b9d57612b9c615135565b5b1415612bde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bd590614ac8565b60405180910390fd5b600480811115612bf157612bf0615135565b5b816004811115612c0457612c03615135565b5b1415612c45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c3c90614b88565b60405180910390fd5b5b50565b6001816000016000828254019250508190555050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612ccf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cc690614a68565b60405180910390fd5b6000612cd961190a565b9050612cea81866000878787612eb2565b612cf78186600087613897565b60008060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905084811015612d7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d7490614c88565b60405180910390fd5b8481036000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508460016000828254612dd49190614f3f565b925050819055508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a4098878787604051612e3c93929190614d03565b60405180910390a3600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef87604051612ea29190614ce8565b60405180910390a3505050505050565b6000731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff1663aabbb8ca877f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe8956040518363ffffffff1660e01b8152600401612f239291906147e8565b60206040518083038186803b158015612f3b57600080fd5b505afa158015612f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f739190613cb5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461301f578073ffffffffffffffffffffffffffffffffffffffff166375ab97828888888888886040518763ffffffff1660e01b8152600401612fec96959493929190614779565b600060405180830381600087803b15801561300657600080fd5b505af115801561301a573d6000803e3d6000fd5b505050505b50505050505050565b61303486868686613897565b60008060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050838110156130ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130b190614a48565b60405180910390fd5b8381036000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550836000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461314d9190614e5e565b925050819055508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc826146779878787876040516131cc93929190614d03565b60405180910390a48473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040516132319190614ce8565b60405180910390a350505050505050565b6000731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff1663aabbb8ca877fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6040518363ffffffff1660e01b81526004016132b39291906147e8565b60206040518083038186803b1580156132cb57600080fd5b505afa1580156132df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133039190613cb5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146133b2578073ffffffffffffffffffffffffffffffffffffffff166223de298989898989896040518763ffffffff1660e01b815260040161337b96959493929190614779565b600060405180830381600087803b15801561339557600080fd5b505af11580156133a9573d6000803e3d6000fd5b50505050613419565b8115613418576133d78673ffffffffffffffffffffffffffffffffffffffff166138b1565b15613417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161340e90614be8565b60405180910390fd5b5b5b5050505050505050565b600081836134319190614e5e565b905092915050565b60008061345b8561345661344c88612235565b868863ffffffff16565b6138d4565b91509150935093915050565b600081836134759190614f3f565b905092915050565b6060600060028360026134909190614ee5565b61349a9190614e5e565b67ffffffffffffffff8111156134b3576134b26151c2565b5b6040519080825280601f01601f1916602001820160405280156134e55781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061351d5761351c615193565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061358157613580615193565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026135c19190614ee5565b6135cb9190614e5e565b90505b600181111561366b577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061360d5761360c615193565b5b1a60f81b82828151811061362457613623615193565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c94508061366490615040565b90506135ce565b50600084146136af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136a690614988565b60405180910390fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415613729576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161372090614ba8565b60405180910390fd5b600061373361190a565b90506137428160008888613897565b84600160008282546137549190614e5e565b92505081905550846000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546137a99190614e5e565b925050819055506137c08160008888888888613242565b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d87878760405161382193929190614d03565b60405180910390a38573ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040516138879190614ce8565b60405180910390a3505050505050565b61389f6128ea565b6138ab84848484613ad6565b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008060008460000180549050905060006138ee86612235565b90506000821180156139445750438660000160018461390d9190614f3f565b8154811061391e5761391d615193565b5b9060005260206000200160000160009054906101000a900463ffffffff1663ffffffff16145b156139d45761395285613adc565b866000016001846139639190614f3f565b8154811061397457613973615193565b5b9060005260206000200160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550613ac7565b8560000160405180604001604052806139ec43613b47565b63ffffffff168152602001613a0088613adc565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16021790555050505b80859350935050509250929050565b50505050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8016821115613b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b3690614bc8565b60405180910390fd5b819050919050565b600063ffffffff8016821115613b92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b8990614c28565b60405180910390fd5b819050919050565b6000613bad613ba884614db1565b614d8c565b905082815260208101848484011115613bc957613bc86151f6565b5b613bd4848285614ffe565b509392505050565b600081359050613beb81615993565b92915050565b600081519050613c0081615993565b92915050565b600081359050613c15816159aa565b92915050565b600081359050613c2a816159c1565b92915050565b600082601f830112613c4557613c446151f1565b5b8135613c55848260208601613b9a565b91505092915050565b600081359050613c6d816159d8565b92915050565b600081359050613c82816159ef565b92915050565b600060208284031215613c9e57613c9d615200565b5b6000613cac84828501613bdc565b91505092915050565b600060208284031215613ccb57613cca615200565b5b6000613cd984828501613bf1565b91505092915050565b60008060408385031215613cf957613cf8615200565b5b6000613d0785828601613bdc565b9250506020613d1885828601613bdc565b9150509250929050565b600080600060608486031215613d3b57613d3a615200565b5b6000613d4986828701613bdc565b9350506020613d5a86828701613bdc565b9250506040613d6b86828701613c5e565b9150509250925092565b600080600080600060a08688031215613d9157613d90615200565b5b6000613d9f88828901613bdc565b9550506020613db088828901613bdc565b9450506040613dc188828901613c5e565b935050606086013567ffffffffffffffff811115613de257613de16151fb565b5b613dee88828901613c30565b925050608086013567ffffffffffffffff811115613e0f57613e0e6151fb565b5b613e1b88828901613c30565b9150509295509295909350565b60008060408385031215613e3f57613e3e615200565b5b6000613e4d85828601613bdc565b9250506020613e5e85828601613c5e565b9150509250929050565b600080600060608486031215613e8157613e80615200565b5b6000613e8f86828701613bdc565b9350506020613ea086828701613c5e565b925050604084013567ffffffffffffffff811115613ec157613ec06151fb565b5b613ecd86828701613c30565b9150509250925092565b60008060008060808587031215613ef157613ef0615200565b5b6000613eff87828801613bdc565b9450506020613f1087828801613c5e565b935050604085013567ffffffffffffffff811115613f3157613f306151fb565b5b613f3d87828801613c30565b925050606085013567ffffffffffffffff811115613f5e57613f5d6151fb565b5b613f6a87828801613c30565b91505092959194509250565b60008060008060008060c08789031215613f9357613f92615200565b5b6000613fa189828a01613bdc565b9650506020613fb289828a01613c5e565b9550506040613fc389828a01613c5e565b9450506060613fd489828a01613c73565b9350506080613fe589828a01613c06565b92505060a0613ff689828a01613c06565b9150509295509295509295565b60006020828403121561401957614018615200565b5b600061402784828501613c06565b91505092915050565b6000806040838503121561404757614046615200565b5b600061405585828601613c06565b925050602061406685828601613bdc565b9150509250929050565b60006020828403121561408657614085615200565b5b600061409484828501613c1b565b91505092915050565b6000602082840312156140b3576140b2615200565b5b60006140c184828501613c5e565b91505092915050565b600080604083850312156140e1576140e0615200565b5b60006140ef85828601613c5e565b925050602083013567ffffffffffffffff8111156141105761410f6151fb565b5b61411c85828601613c30565b9150509250929050565b6000614132838361413e565b60208301905092915050565b61414781614f73565b82525050565b61415681614f73565b82525050565b600061416782614df2565b6141718185614e20565b935061417c83614de2565b8060005b838110156141ad5781516141948882614126565b975061419f83614e13565b925050600181019050614180565b5085935050505092915050565b6141c381614f85565b82525050565b6141d281614f91565b82525050565b6141e96141e482614f91565b6150cd565b82525050565b60006141fa82614dfd565b6142048185614e31565b935061421481856020860161500d565b61421d81615205565b840191505092915050565b600061423382614e08565b61423d8185614e42565b935061424d81856020860161500d565b61425681615205565b840191505092915050565b600061426c82614e08565b6142768185614e53565b935061428681856020860161500d565b80840191505092915050565b600061429f601883614e42565b91506142aa82615216565b602082019050919050565b60006142c2602083614e42565b91506142cd8261523f565b602082019050919050565b60006142e5601983614e42565b91506142f082615268565b602082019050919050565b6000614308601483614e42565b915061431382615291565b602082019050919050565b600061432b602583614e42565b9150614336826152ba565b604082019050919050565b600061434e601483614e42565b915061435982615309565b602082019050919050565b6000614371601f83614e42565b915061437c82615332565b602082019050919050565b6000614394602783614e42565b915061439f8261535b565b604082019050919050565b60006143b7600283614e53565b91506143c2826153aa565b600282019050919050565b60006143da602283614e42565b91506143e5826153d3565b604082019050919050565b60006143fd601e83614e42565b915061440882615422565b602082019050919050565b6000614420602483614e42565b915061442b8261544b565b604082019050919050565b6000614443602283614e42565b915061444e8261549a565b604082019050919050565b6000614466602083614e42565b9150614471826154e9565b602082019050919050565b6000614489602183614e42565b915061449482615512565b604082019050919050565b60006144ac601083614e42565b91506144b782615561565b602082019050919050565b60006144cf601883614e42565b91506144da8261558a565b602082019050919050565b60006144f2601a83614e42565b91506144fd826155b3565b602082019050919050565b6000614515602283614e42565b9150614520826155dc565b604082019050919050565b6000614538602083614e42565b91506145438261562b565b602082019050919050565b600061455b602783614e42565b915061456682615654565b604082019050919050565b600061457e604d83614e42565b9150614589826156a3565b606082019050919050565b60006145a1602483614e42565b91506145ac82615718565b604082019050919050565b60006145c4602683614e42565b91506145cf82615767565b604082019050919050565b60006145e7602c83614e42565b91506145f2826157b6565b604082019050919050565b600061460a601783614e53565b915061461582615805565b601782019050919050565b600061462d602683614e42565b91506146388261582e565b604082019050919050565b6000614650602383614e42565b915061465b8261587d565b604082019050919050565b6000614673602383614e42565b915061467e826158cc565b604082019050919050565b6000614696601183614e53565b91506146a18261591b565b601182019050919050565b60006146b9602f83614e42565b91506146c482615944565b604082019050919050565b6146d881614fe7565b82525050565b6146e781614ff1565b82525050565b60006146f8826143aa565b915061470482856141d8565b60208201915061471482846141d8565b6020820191508190509392505050565b600061472f826145fd565b915061473b8285614261565b915061474682614689565b91506147528284614261565b91508190509392505050565b6000602082019050614773600083018461414d565b92915050565b600060c08201905061478e600083018961414d565b61479b602083018861414d565b6147a8604083018761414d565b6147b560608301866146cf565b81810360808301526147c781856141ef565b905081810360a08301526147db81846141ef565b9050979650505050505050565b60006040820190506147fd600083018561414d565b61480a60208301846141c9565b9392505050565b6000602082019050818103600083015261482b818461415c565b905092915050565b600060208201905061484860008301846141ba565b92915050565b600060208201905061486360008301846141c9565b92915050565b600060808201905061487e60008301876141c9565b61488b602083018661414d565b61489860408301856146cf565b6148a560608301846146cf565b95945050505050565b600060a0820190506148c360008301886141c9565b6148d060208301876141c9565b6148dd60408301866141c9565b6148ea60608301856146cf565b6148f7608083018461414d565b9695505050505050565b600060808201905061491660008301876141c9565b61492360208301866146de565b61493060408301856141c9565b61493d60608301846141c9565b95945050505050565b600060208201905081810360008301526149608184614228565b905092915050565b6000602082019050818103600083015261498181614292565b9050919050565b600060208201905081810360008301526149a1816142b5565b9050919050565b600060208201905081810360008301526149c1816142d8565b9050919050565b600060208201905081810360008301526149e1816142fb565b9050919050565b60006020820190508181036000830152614a018161431e565b9050919050565b60006020820190508181036000830152614a2181614341565b9050919050565b60006020820190508181036000830152614a4181614364565b9050919050565b60006020820190508181036000830152614a6181614387565b9050919050565b60006020820190508181036000830152614a81816143cd565b9050919050565b60006020820190508181036000830152614aa1816143f0565b9050919050565b60006020820190508181036000830152614ac181614413565b9050919050565b60006020820190508181036000830152614ae181614436565b9050919050565b60006020820190508181036000830152614b0181614459565b9050919050565b60006020820190508181036000830152614b218161447c565b9050919050565b60006020820190508181036000830152614b418161449f565b9050919050565b60006020820190508181036000830152614b61816144c2565b9050919050565b60006020820190508181036000830152614b81816144e5565b9050919050565b60006020820190508181036000830152614ba181614508565b9050919050565b60006020820190508181036000830152614bc18161452b565b9050919050565b60006020820190508181036000830152614be18161454e565b9050919050565b60006020820190508181036000830152614c0181614571565b9050919050565b60006020820190508181036000830152614c2181614594565b9050919050565b60006020820190508181036000830152614c41816145b7565b9050919050565b60006020820190508181036000830152614c61816145da565b9050919050565b60006020820190508181036000830152614c8181614620565b9050919050565b60006020820190508181036000830152614ca181614643565b9050919050565b60006020820190508181036000830152614cc181614666565b9050919050565b60006020820190508181036000830152614ce1816146ac565b9050919050565b6000602082019050614cfd60008301846146cf565b92915050565b6000606082019050614d1860008301866146cf565b8181036020830152614d2a81856141ef565b90508181036040830152614d3e81846141ef565b9050949350505050565b6000604082019050614d5d60008301856146cf565b614d6a60208301846146cf565b9392505050565b6000602082019050614d8660008301846146de565b92915050565b6000614d96614da7565b9050614da2828261509c565b919050565b6000604051905090565b600067ffffffffffffffff821115614dcc57614dcb6151c2565b5b614dd582615205565b9050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b6000614e6982614fe7565b9150614e7483614fe7565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614ea957614ea86150d7565b5b828201905092915050565b6000614ebf82614fe7565b9150614eca83614fe7565b925082614eda57614ed9615106565b5b828204905092915050565b6000614ef082614fe7565b9150614efb83614fe7565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614f3457614f336150d7565b5b828202905092915050565b6000614f4a82614fe7565b9150614f5583614fe7565b925082821015614f6857614f676150d7565b5b828203905092915050565b6000614f7e82614fc7565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b8381101561502b578082015181840152602081019050615010565b8381111561503a576000848401525b50505050565b600061504b82614fe7565b9150600082141561505f5761505e6150d7565b5b600182039050919050565b6000600282049050600182168061508257607f821691505b6020821081141561509657615095615164565b5b50919050565b6150a582615205565b810181811067ffffffffffffffff821117156150c4576150c36151c2565b5b80604052505050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b7f4d6174636869546f6b656e3a2063617020657863656564656400000000000000600082015250565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b7f4552433737373a20617070726f76652066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f566f7465733a20696e76616c6964206e6f6e6365000000000000000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b7f4552433737373a207472616e7366657220616d6f756e7420657863656564732060008201527f62616c616e636500000000000000000000000000000000000000000000000000602082015250565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433737373a206275726e2066726f6d20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a20696e73756666696369656e7420616c6c6f77616e63650000600082015250565b7f4552433737373a20617574686f72697a696e672073656c66206173206f70657260008201527f61746f7200000000000000000000000000000000000000000000000000000000602082015250565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f436865636b706f696e74733a20626c6f636b206e6f7420796574206d696e6564600082015250565b7f4552433737373a207265766f6b696e672073656c66206173206f70657261746f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b7f566f7465733a207369676e617475726520657870697265640000000000000000600082015250565b7f566f7465733a20626c6f636b206e6f7420796574206d696e6564000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203260008201527f3234206269747300000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a20746f6b656e20726563697069656e7420636f6e747261637460008201527f20686173206e6f20696d706c656d656e74657220666f7220455243373737546f60208201527f6b656e73526563697069656e7400000000000000000000000000000000000000604082015250565b7f4552433737373a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f53616665436173743a2076616c756520646f65736e27742066697420696e203360008201527f3220626974730000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a2063616c6c6572206973206e6f7420616e206f70657261746f60008201527f7220666f7220686f6c6465720000000000000000000000000000000000000000602082015250565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b7f4552433737373a207472616e736665722066726f6d20746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a206275726e20616d6f756e7420657863656564732062616c6160008201527f6e63650000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433737373a20617070726f766520746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b61599c81614f73565b81146159a757600080fd5b50565b6159b381614f91565b81146159be57600080fd5b50565b6159ca81614f9b565b81146159d557600080fd5b50565b6159e181614fe7565b81146159ec57600080fd5b50565b6159f881614ff1565b8114615a0357600080fd5b5056fea264697066735822122023836b8516fd7aad97d60b9e3b1f005bf632f16bb28d0a2fdf5ea7be98822dfc64736f6c63430008070033

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

000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : capacity (uint256): 1000000000

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000003b9aca00
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

139082:2516:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90546:204;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;126532:132;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122864:100;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;128344:201;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123690:125;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;129041:326;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92382:131;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92823:147;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123321:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;140099:83;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;87694:106;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93967:218;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;82760:186;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;139768:77;;;:::i;:::-;;141279:115;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123527:97;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;83949:129;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84165:150;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;97901:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;126790:375;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123920:152;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;87432:119;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;139687:73;;;:::i;:::-;;83422:239;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;90842:147;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;125557:422;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123025:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;82393:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124209:199;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;89947:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124649:186;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84398:581;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;139221:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93263:149;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125169:316;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;127874:153;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;139152:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;126048:413;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;127293:333;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124972:129;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;90546:204;90631:4;90670:32;90655:47;;;:11;:47;;;;:87;;;;90706:36;90730:11;90706:23;:36::i;:::-;90655:87;90648:94;;90546:204;;;:::o;126532:132::-;126598:16;126634:22;126627:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126532:132;:::o;122864:100::-;122918:13;122951:5;122944:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122864:100;:::o;128344:201::-;128426:4;128443:14;128460:12;:10;:12::i;:::-;128443:29;;128483:32;128492:6;128500:7;128509:5;128483:8;:32::i;:::-;128533:4;128526:11;;;128344:201;;;;:::o;123690:125::-;123768:7;123795:12;;123788:19;;123690:125;:::o;129041:326::-;129181:4;129198:15;129216:12;:10;:12::i;:::-;129198:30;;129239:40;129255:6;129263:7;129272:6;129239:15;:40::i;:::-;129290:47;129296:6;129304:9;129315:6;129290:47;;;;;;;;;;;;;;;;;;;;;;;;129331:5;129290;:47::i;:::-;129355:4;129348:11;;;129041:326;;;;;:::o;92382:131::-;92456:7;92483:6;:12;92490:4;92483:12;;;;;;;;;;;:22;;;92476:29;;92382:131;;;:::o;92823:147::-;92906:18;92919:4;92906:12;:18::i;:::-;90438:16;90449:4;90438:10;:16::i;:::-;92937:25:::1;92948:4;92954:7;92937:10;:25::i;:::-;92823:147:::0;;;:::o;123321:84::-;123370:5;123395:2;123388:9;;123321:84;:::o;140099:83::-;140143:7;140170:4;140163:11;;140099:83;:::o;87694:106::-;87745:7;87772:20;:18;:20::i;:::-;87765:27;;87694:106;:::o;93967:218::-;94074:12;:10;:12::i;:::-;94063:23;;:7;:23;;;94055:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;94151:26;94163:4;94169:7;94151:11;:26::i;:::-;93967:218;;:::o;82760:186::-;82858:7;82885:53;82926:11;82885:20;:29;82906:7;82885:29;;;;;;;;;;;;;;;:40;;:53;;;;:::i;:::-;82878:60;;82760:186;;;;:::o;139768:77::-;139190:24;90438:16;90449:4;90438:10;:16::i;:::-;139827:10:::1;:8;:10::i;:::-;139768:77:::0;:::o;141279:115::-;139259:24;90438:16;90449:4;90438:10;:16::i;:::-;141361:25:::1;141367:2;141371:6;141361:25;;;;;;;;;;;::::0;::::1;;;;;;;;;;;::::0;:5:::1;:25::i;:::-;141279:115:::0;;;:::o;123527:97::-;123588:7;123615:1;123608:8;;123527:97;:::o;83949:129::-;84023:7;84050:11;:20;84062:7;84050:20;;;;;;;;;;;;;;;;;;;;;;;;;84043:27;;83949:129;;;:::o;84165:150::-;84237:15;84255:12;:10;:12::i;:::-;84237:30;;84278:29;84288:7;84297:9;84278;:29::i;:::-;84226:89;84165:150;:::o;97901:86::-;97948:4;97972:7;;;;;;;;;;;97965:14;;97901:86;:::o;126790:375::-;127004:35;127018:12;:10;:12::i;:::-;127032:6;127004:13;:35::i;:::-;126996:92;;;;;;;;;;;;:::i;:::-;;;;;;;;;127099:58;127105:6;127113:9;127124:6;127132:4;127138:12;127152:4;127099:5;:58::i;:::-;126790:375;;;;;:::o;123920:152::-;124015:7;124042:9;:22;124052:11;124042:22;;;;;;;;;;;;;;;;124035:29;;123920:152;;;:::o;87432:119::-;87492:7;87519:24;:7;:14;87527:5;87519:14;;;;;;;;;;;;;;;:22;:24::i;:::-;87512:31;;87432:119;;;:::o;139687:73::-;139190:24;90438:16;90449:4;90438:10;:16::i;:::-;139744:8:::1;:6;:8::i;:::-;139687:73:::0;:::o;83422:239::-;83509:7;83551:12;83537:11;:26;83529:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;83612:41;83641:11;83612:17;:28;;:41;;;;:::i;:::-;83605:48;;83422:239;;;:::o;90842:147::-;90928:4;90952:6;:12;90959:4;90952:12;;;;;;;;;;;:20;;:29;90973:7;90952:29;;;;;;;;;;;;;;;;;;;;;;;;;90945:36;;90842:147;;;;:::o;125557:422::-;125661:8;125645:24;;:12;:10;:12::i;:::-;:24;;;;125637:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;125727:17;:27;125745:8;125727:27;;;;;;;;;;;;;;;;;;;;;;;;;125723:189;;;125778:24;:38;125803:12;:10;:12::i;:::-;125778:38;;;;;;;;;;;;;;;:48;125817:8;125778:48;;;;;;;;;;;;;;;;125771:55;;;;;;;;;;;125723:189;;;125896:4;125859:10;:24;125870:12;:10;:12::i;:::-;125859:24;;;;;;;;;;;;;;;:34;125884:8;125859:34;;;;;;;;;;;;;;;;:41;;;;;;;;;;;;;;;;;;125723:189;125958:12;:10;:12::i;:::-;125929:42;;125948:8;125929:42;;;;;;;;;;;;125557:422;:::o;123025:104::-;123081:13;123114:7;123107:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123025:104;:::o;82393:146::-;82466:7;82493:38;:20;:29;82514:7;82493:29;;;;;;;;;;;;;;;:36;:38::i;:::-;82486:45;;82393:146;;;:::o;124209:199::-;124346:54;124352:12;:10;:12::i;:::-;124366:9;124377:6;124385:4;124346:54;;;;;;;;;;;;124395:4;124346:5;:54::i;:::-;124209:199;;;:::o;89947:49::-;89992:4;89947:49;;;:::o;124649:186::-;124735:4;124752:53;124758:12;:10;:12::i;:::-;124772:9;124783:6;124752:53;;;;;;;;;;;;;;;;;;;;;;;;124799:5;124752;:53::i;:::-;124823:4;124816:11;;124649:186;;;;:::o;84398:581::-;84625:6;84606:15;:25;;84598:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;84671:14;84688:174;84716:87;81982:71;84776:9;84787:5;84794:6;84743:58;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;84733:69;;;;;;84716:16;:87::i;:::-;84818:1;84834;84850;84688:13;:174::i;:::-;84671:191;;84890:17;84900:6;84890:9;:17::i;:::-;84881:5;:26;84873:59;;;;;;;;;;;;:::i;:::-;;;;;;;;;84943:28;84953:6;84961:9;84943;:28::i;:::-;84587:392;84398:581;;;;;;:::o;139221:62::-;139259:24;139221:62;:::o;93263:149::-;93347:18;93360:4;93347:12;:18::i;:::-;90438:16;90449:4;90438:10;:16::i;:::-;93378:26:::1;93390:4;93396:7;93378:11;:26::i;:::-;93263:149:::0;;;:::o;125169:316::-;125269:4;125318:11;125306:23;;:8;:23;;;:121;;;;125347:17;:27;125365:8;125347:27;;;;;;;;;;;;;;;;;;;;;;;;;:79;;;;;125379:24;:37;125404:11;125379:37;;;;;;;;;;;;;;;:47;125417:8;125379:47;;;;;;;;;;;;;;;;;;;;;;;;;125378:48;125347:79;125306:121;:171;;;;125444:10;:23;125455:11;125444:23;;;;;;;;;;;;;;;:33;125468:8;125444:33;;;;;;;;;;;;;;;;;;;;;;;;;125306:171;125286:191;;125169:316;;;;:::o;127874:153::-;127964:7;127991:11;:19;128003:6;127991:19;;;;;;;;;;;;;;;:28;128011:7;127991:28;;;;;;;;;;;;;;;;127984:35;;127874:153;;;;:::o;139152:62::-;139190:24;139152:62;:::o;126048:413::-;126145:12;:10;:12::i;:::-;126133:24;;:8;:24;;;;126125:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;126212:17;:27;126230:8;126212:27;;;;;;;;;;;;;;;;;;;;;;;;;126208:189;;;126307:4;126256:24;:38;126281:12;:10;:12::i;:::-;126256:38;;;;;;;;;;;;;;;:48;126295:8;126256:48;;;;;;;;;;;;;;;;:55;;;;;;;;;;;;;;;;;;126208:189;;;126351:10;:24;126362:12;:10;:12::i;:::-;126351:24;;;;;;;;;;;;;;;:34;126376:8;126351:34;;;;;;;;;;;;;;;;126344:41;;;;;;;;;;;126208:189;126440:12;:10;:12::i;:::-;126414:39;;126430:8;126414:39;;;;;;;;;;;;126048:413;:::o;127293:333::-;127480:36;127494:12;:10;:12::i;:::-;127508:7;127480:13;:36::i;:::-;127472:93;;;;;;;;;;;;:::i;:::-;;;;;;;;;127576:42;127582:7;127591:6;127599:4;127605:12;127576:5;:42::i;:::-;127293:333;;;;:::o;124972:129::-;125056:37;125062:12;:10;:12::i;:::-;125076:6;125084:4;125056:37;;;;;;;;;;;;:5;:37::i;:::-;124972:129;;:::o;54328:157::-;54413:4;54452:25;54437:40;;;:11;:40;;;;54430:47;;54328:157;;;:::o;80002:98::-;80055:7;80082:10;80075:17;;80002:98;:::o;134715:383::-;134869:1;134851:20;;:6;:20;;;;134843:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;134951:1;134932:21;;:7;:21;;;;134924:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;135037:5;135006:11;:19;135018:6;135006:19;;;;;;;;;;;;;;;:28;135026:7;135006:28;;;;;;;;;;;;;;;:36;;;;135075:7;135058:32;;135067:6;135058:32;;;135084:5;135058:32;;;;;;:::i;:::-;;;;;;;;134715:383;;;:::o;137750:454::-;137885:24;137912:25;137922:5;137929:7;137912:9;:25::i;:::-;137885:52;;137972:17;137952:16;:37;137948:249;;138034:6;138014:16;:26;;138006:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;138119:51;138128:5;138135:7;138163:6;138144:16;:25;138119:8;:51::i;:::-;137948:249;137874:330;137750:454;;;:::o;140909:362::-;141140:74;141152:4;141158:2;141162:6;141170:8;141180:12;141194:19;141140:11;:74::i;:::-;141225:38;141246:4;141252:2;141256:6;141225:20;:38::i;:::-;140909:362;;;;;;:::o;91293:105::-;91360:30;91371:4;91377:12;:10;:12::i;:::-;91360:10;:30::i;:::-;91293:105;:::o;95564:238::-;95648:22;95656:4;95662:7;95648;:22::i;:::-;95643:152;;95719:4;95687:6;:12;95694:4;95687:12;;;;;;;;;;;:20;;:29;95708:7;95687:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;95770:12;:10;:12::i;:::-;95743:40;;95761:7;95743:40;;95755:4;95743:40;;;;;;;;;;95643:152;95564:238;;:::o;69849:314::-;69902:7;69943:12;69926:29;;69934:4;69926:29;;;:66;;;;;69976:16;69959:13;:33;69926:66;69922:234;;;70016:24;70009:31;;;;69922:234;70080:64;70102:10;70114:12;70128:15;70080:21;:64::i;:::-;70073:71;;69849:314;;:::o;95982:239::-;96066:22;96074:4;96080:7;96066;:22::i;:::-;96062:152;;;96137:5;96105:6;:12;96112:4;96105:12;;;;;;;;;;;:20;;:29;96126:7;96105:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;96189:12;:10;:12::i;:::-;96162:40;;96180:7;96162:40;;96174:4;96162:40;;;;;;;;;;96062:152;95982:239;;:::o;49257:592::-;49343:7;49385:12;49371:11;:26;49363:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;49447:12;49462:4;:17;;:24;;;;49447:39;;49497:11;49523:251;49536:4;49530:3;:10;49523:251;;;49557:11;49571:23;49584:3;49589:4;49571:12;:23::i;:::-;49557:37;;49651:11;49613:4;:17;;49631:3;49613:22;;;;;;;;:::i;:::-;;;;;;;;;:35;;;;;;;;;;;;:49;;;49609:154;;;49690:3;49683:10;;49609:154;;;49746:1;49740:3;:7;;;;:::i;:::-;49734:13;;49609:154;49542:232;49523:251;;;49799:1;49791:4;:9;:50;;49807:4;:17;;49832:1;49825:4;:8;;;;:::i;:::-;49807:27;;;;;;;;:::i;:::-;;;;;;;;;:34;;;;;;;;;;;;49791:50;;;49803:1;49791:50;49784:57;;;;;;49257:592;;;;:::o;98756:120::-;97765:16;:14;:16::i;:::-;98825:5:::1;98815:7;;:15;;;;;;;;;;;;;;;;;;98846:22;98855:12;:10;:12::i;:::-;98846:22;;;;;;:::i;:::-;;;;;;;;98756:120::o:0;140190:422::-;140423:5;:3;:5::i;:::-;140413:6;140390:20;:18;:20::i;:::-;:29;;;;:::i;:::-;:38;;140368:113;;;;;;;;;;;;:::i;:::-;;;;;;;;;140492:52;140504:7;140513:6;140521:8;140531:12;140492:11;:52::i;:::-;140555:49;140584:1;140588:7;140597:6;140555:20;:49::i;:::-;140190:422;;;;:::o;85150:319::-;85233:19;85255:18;85265:7;85255:9;:18::i;:::-;85233:40;;85307:9;85284:11;:20;85296:7;85284:20;;;;;;;;;;;;;;;;:32;;;;;;;;;;;;;;;;;;85372:9;85334:48;;85359:11;85334:48;;85350:7;85334:48;;;;;;;;;;;;85393:68;85412:11;85425:9;85436:24;85452:7;85436:15;:24::i;:::-;85393:18;:68::i;:::-;85222:247;85150:319;;:::o;51953:114::-;52018:7;52045;:14;;;52038:21;;51953:114;;;:::o;98497:118::-;97506:19;:17;:19::i;:::-;98567:4:::1;98557:7;;:14;;;;;;;;;;;;;;;;;;98587:20;98594:12;:10;:12::i;:::-;98587:20;;;;;;:::i;:::-;;;;;;;;98497:118::o:0;48868:193::-;48929:7;48949:11;48963:4;:17;;:24;;;;48949:38;;49012:1;49005:3;:8;:48;;49020:4;:17;;49044:1;49038:3;:7;;;;:::i;:::-;49020:26;;;;;;;;:::i;:::-;;;;;;;;;:33;;;;;;;;;;;;49005:48;;;49016:1;49005:48;48998:55;;;;;48868:193;;;:::o;71076:167::-;71153:7;71180:55;71202:20;:18;:20::i;:::-;71224:10;71180:21;:55::i;:::-;71173:62;;71076:167;;;:::o;64725:279::-;64853:7;64874:17;64893:18;64915:25;64926:4;64932:1;64935;64938;64915:10;:25::i;:::-;64873:67;;;;64951:18;64963:5;64951:11;:18::i;:::-;64987:9;64980:16;;;;64725:279;;;;;;:::o;87160:207::-;87220:15;87248:30;87281:7;:14;87289:5;87281:14;;;;;;;;;;;;;;;87248:47;;87316:15;:5;:13;:15::i;:::-;87306:25;;87342:17;:5;:15;:17::i;:::-;87237:130;87160:207;;;:::o;140620:281::-;140791:45;140803:4;140809:6;140817:4;140823:12;140791:11;:45::i;:::-;140847:46;140868:4;140882:1;140886:6;140847:20;:46::i;:::-;140620:281;;;;:::o;132107:676::-;132353:1;132337:18;;:4;:18;;;;132329:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;132431:1;132417:16;;:2;:16;;;;132409:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;132487:16;132506:12;:10;:12::i;:::-;132487:31;;132531:69;132549:8;132559:4;132565:2;132569:6;132577:8;132587:12;132531:17;:69::i;:::-;132613:57;132619:8;132629:4;132635:2;132639:6;132647:8;132657:12;132613:5;:57::i;:::-;132683:92;132703:8;132713:4;132719:2;132723:6;132731:8;132741:12;132755:19;132683;:92::i;:::-;132318:465;132107:676;;;;;;:::o;85709:397::-;85863:1;85847:18;;:4;:18;;;85843:87;;;85882:36;85905:4;85911:6;85882:17;:22;;:36;;;;;:::i;:::-;;;85843:87;85958:1;85944:16;;:2;:16;;;85940:90;;;85977:41;86000:9;86011:6;85977:17;:22;;:41;;;;;:::i;:::-;;;85940:90;86040:58;86059:15;86069:4;86059:9;:15::i;:::-;86076:13;86086:2;86076:9;:13::i;:::-;86091:6;86040:18;:58::i;:::-;85709:397;;;:::o;91688:505::-;91777:22;91785:4;91791:7;91777;:22::i;:::-;91772:414;;91965:41;91993:7;91965:41;;92003:2;91965:19;:41::i;:::-;92079:38;92107:4;92099:13;;92114:2;92079:19;:38::i;:::-;91870:270;;;;;;;;;:::i;:::-;;;;;;;;;;;;;91816:358;;;;;;;;;;;:::i;:::-;;;;;;;;91772:414;91688:505;;:::o;70171:263::-;70315:7;70363:8;70373;70383:11;70396:13;70419:4;70352:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;70342:84;;;;;;70335:91;;70171:263;;;;;:::o;39751:156::-;39813:7;39898:1;39893;39889;:5;39888:11;;;;:::i;:::-;39883:1;39879;:5;39878:21;;;;:::i;:::-;39871:28;;39751:156;;;;:::o;98245:108::-;98312:8;:6;:8::i;:::-;98304:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;98245:108::o;130002:229::-;130171:52;130177:7;130186:6;130194:8;130204:12;130218:4;130171:5;:52::i;:::-;130002:229;;;;:::o;141402:193::-;141533:7;141565:22;141575:11;141565:9;:22::i;:::-;141558:29;;141402:193;;;:::o;86197:625::-;86332:2;86324:10;;:4;:10;;;;:24;;;;;86347:1;86338:6;:10;86324:24;86320:495;;;86385:1;86369:18;;:4;:18;;;86365:218;;86409:16;86427;86447:50;86479:9;86490:6;86447:20;:26;86468:4;86447:26;;;;;;;;;;;;;;;:31;;:50;;;;;:::i;:::-;86408:89;;;;86542:4;86521:46;;;86548:8;86558;86521:46;;;;;;;:::i;:::-;;;;;;;;86389:194;;86365:218;86615:1;86601:16;;:2;:16;;;86597:207;;86639:16;86657;86677:43;86707:4;86713:6;86677:20;:24;86698:2;86677:24;;;;;;;;;;;;;;;:29;;:43;;;;;:::i;:::-;86638:82;;;;86765:2;86744:44;;;86769:8;86779;86744:44;;;;;;;:::i;:::-;;;;;;;;86619:185;;86597:207;86320:495;86197:625;;;:::o;98060:108::-;98131:8;:6;:8::i;:::-;98130:9;98122:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;98060:108::o;66416:196::-;66509:7;66575:15;66592:10;66546:57;;;;;;;;;:::i;:::-;;;;;;;;;;;;;66536:68;;;;;;66529:75;;66416:196;;;;:::o;62954:1632::-;63085:7;63094:12;64019:66;64014:1;64006:10;;:79;64002:163;;;64118:1;64122:30;64102:51;;;;;;64002:163;64184:2;64179:1;:7;;;;:18;;;;;64195:2;64190:1;:7;;;;64179:18;64175:102;;;64230:1;64234:30;64214:51;;;;;;64175:102;64374:14;64391:24;64401:4;64407:1;64410;64413;64391:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64374:41;;64448:1;64430:20;;:6;:20;;;64426:103;;;64483:1;64487:29;64467:50;;;;;;;64426:103;64549:6;64557:20;64541:37;;;;;62954:1632;;;;;;;;:::o;57567:643::-;57645:20;57636:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;57632:571;;;57682:7;;57632:571;57743:29;57734:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;57730:473;;;57789:34;;;;;;;;;;:::i;:::-;;;;;;;;57730:473;57854:35;57845:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;57841:362;;;57906:41;;;;;;;;;;:::i;:::-;;;;;;;;57841:362;57978:30;57969:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;57965:238;;;58025:44;;;;;;;;;;:::i;:::-;;;;;;;;57965:238;58100:30;58091:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;58087:116;;;58147:44;;;;;;;;;;:::i;:::-;;;;;;;;58087:116;57567:643;;:::o;52075:127::-;52182:1;52164:7;:14;;;:19;;;;;;;;;;;52075:127;:::o;133097:835::-;133283:1;133267:18;;:4;:18;;;;133259:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;133337:16;133356:12;:10;:12::i;:::-;133337:31;;133381:73;133399:8;133409:4;133423:1;133427:6;133435:4;133441:12;133381:17;:73::i;:::-;133467:56;133488:8;133498:4;133512:1;133516:6;133467:20;:56::i;:::-;133571:19;133593:9;:15;133603:4;133593:15;;;;;;;;;;;;;;;;133571:37;;133642:6;133627:11;:21;;133619:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;133756:6;133742:11;:20;133724:9;:15;133734:4;133724:15;;;;;;;;;;;;;;;:38;;;;133800:6;133784:12;;:22;;;;;;;:::i;:::-;;;;;;;;133841:4;133824:50;;133831:8;133824:50;;;133847:6;133855:4;133861:12;133824:50;;;;;;;;:::i;:::-;;;;;;;;133913:1;133890:34;;133899:4;133890:34;;;133917:6;133890:34;;;;;;:::i;:::-;;;;;;;;133248:684;;133097:835;;;;:::o;135582:484::-;135799:19;121075:42;135821:41;;;135863:4;121333:31;135821:78;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135799:100;;135937:1;135914:25;;:11;:25;;;135910:149;;135970:11;135956:39;;;135996:8;136006:4;136012:2;136016:6;136024:8;136034:12;135956:91;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135910:149;135788:278;135582:484;;;;;;:::o;133940:630::-;134145:48;134166:8;134176:4;134182:2;134186:6;134145:20;:48::i;:::-;134206:19;134228:9;:15;134238:4;134228:15;;;;;;;;;;;;;;;;134206:37;;134277:6;134262:11;:21;;134254:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;134395:6;134381:11;:20;134363:9;:15;134373:4;134363:15;;;;;;;;;;;;;;;:38;;;;134440:6;134423:9;:13;134433:2;134423:13;;;;;;;;;;;;;;;;:23;;;;;;;:::i;:::-;;;;;;;;134485:2;134464:56;;134479:4;134464:56;;134469:8;134464:56;;;134489:6;134497:8;134507:12;134464:56;;;;;;;;:::i;:::-;;;;;;;;134551:2;134536:26;;134545:4;134536:26;;;134555:6;134536:26;;;;;;:::i;:::-;;;;;;;;134134:436;133940:630;;;;;;:::o;136768:691::-;137022:19;121075:42;137044:41;;;137086:2;121431:34;137044:79;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137022:101;;137161:1;137138:25;;:11;:25;;;137134:318;;137197:11;137180:44;;;137225:8;137235:4;137241:2;137245:6;137253:8;137263:12;137180:96;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137134:318;;;137298:19;137294:158;;;137343:15;:2;:13;;;:15::i;:::-;137342:16;137334:106;;;;;;;;;;;;:::i;:::-;;;;;;;;;137294:158;137134:318;137011:448;136768:691;;;;;;;:::o;86830:98::-;86888:7;86919:1;86915;:5;;;;:::i;:::-;86908:12;;86830:98;;;;:::o;50838:236::-;50995:7;51004;51031:35;51036:4;51042:23;51045:12;51052:4;51045:6;:12::i;:::-;51059:5;51042:2;:23;;:::i;:::-;51031:4;:35::i;:::-;51024:42;;;;50838:236;;;;;;:::o;86936:103::-;86999:7;87030:1;87026;:5;;;;:::i;:::-;87019:12;;86936:103;;;;:::o;56223:451::-;56298:13;56324:19;56369:1;56360:6;56356:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;56346:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56324:47;;56382:15;:6;56389:1;56382:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;56408;:6;56415:1;56408:9;;;;;;;;:::i;:::-;;;;;:15;;;;;;;;;;;56439:9;56464:1;56455:6;56451:1;:10;;;;:::i;:::-;:14;;;;:::i;:::-;56439:26;;56434:135;56471:1;56467;:5;56434:135;;;56506:12;56527:3;56519:5;:11;56506:25;;;;;;;:::i;:::-;;;;;56494:6;56501:1;56494:9;;;;;;;;:::i;:::-;;;;;:37;;;;;;;;;;;56556:1;56546:11;;;;;56474:3;;;;:::i;:::-;;;56434:135;;;;56596:1;56587:5;:10;56579:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;56659:6;56645:21;;;56223:451;;;;:::o;130873:747::-;131104:1;131085:21;;:7;:21;;;;131077:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;131156:16;131175:12;:10;:12::i;:::-;131156:31;;131200:59;131221:8;131239:1;131243:7;131252:6;131200:20;:59::i;:::-;131323:6;131307:12;;:22;;;;;;;:::i;:::-;;;;;;;;131362:6;131340:9;:18;131350:7;131340:18;;;;;;;;;;;;;;;;:28;;;;;;;:::i;:::-;;;;;;;;131381:103;131401:8;131419:1;131423:7;131432:6;131440:8;131450:12;131464:19;131381;:103::i;:::-;131519:7;131502:57;;131509:8;131502:57;;;131528:6;131536:8;131546:12;131502:57;;;;;;;;:::i;:::-;;;;;;;;131596:7;131575:37;;131592:1;131575:37;;;131605:6;131575:37;;;;;;:::i;:::-;;;;;;;;131066:554;130873:747;;;;;:::o;139853:238::-;97506:19;:17;:19::i;:::-;140029:54:::1;140056:8;140066:4;140072:2;140076:6;140029:26;:54::i;:::-;139853:238:::0;;;;:::o;100116:326::-;100176:4;100433:1;100411:7;:19;;;:23;100404:30;;100116:326;;;:::o;50034:564::-;50103:7;50112;50132:11;50146:4;:17;;:24;;;;50132:38;;50181:11;50195:12;50202:4;50195:6;:12::i;:::-;50181:26;;50228:1;50222:3;:7;:66;;;;;50276:12;50233:4;:17;;50257:1;50251:3;:7;;;;:::i;:::-;50233:26;;;;;;;;:::i;:::-;;;;;;;;;:39;;;;;;;;;;;;:55;;;50222:66;50218:343;;;50341:25;50360:5;50341:18;:25::i;:::-;50305:4;:17;;50329:1;50323:3;:7;;;;:::i;:::-;50305:26;;;;;;;;:::i;:::-;;;;;;;;;:33;;;:61;;;;;;;;;;;;;;;;;;50218:343;;;50399:4;:17;;50440:94;;;;;;;;50466:31;50484:12;50466:17;:31::i;:::-;50440:94;;;;;;50507:25;50526:5;50507:18;:25::i;:::-;50440:94;;;;;50399:150;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50218:343;50579:3;50584:5;50571:19;;;;;;50034:564;;;;;:::o;138848:152::-;;;;;:::o;5057:195::-;5114:7;5151:17;5142:26;;:5;:26;;5134:78;;;;;;;;;;;;:::i;:::-;;;;;;;;;5238:5;5223:21;;5057:195;;;:::o;17893:190::-;17949:6;17985:16;17976:25;;:5;:25;;17968:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;18069:5;18055:20;;17893:190;;;:::o;7:410:1:-;84:5;109:65;125:48;166:6;125:48;:::i;:::-;109:65;:::i;:::-;100:74;;197:6;190:5;183:21;235:4;228:5;224:16;273:3;264:6;259:3;255:16;252:25;249:112;;;280:79;;:::i;:::-;249:112;370:41;404:6;399:3;394;370:41;:::i;:::-;90:327;7:410;;;;;:::o;423:139::-;469:5;507:6;494:20;485:29;;523:33;550:5;523:33;:::i;:::-;423:139;;;;:::o;568:143::-;625:5;656:6;650:13;641:22;;672:33;699:5;672:33;:::i;:::-;568:143;;;;:::o;717:139::-;763:5;801:6;788:20;779:29;;817:33;844:5;817:33;:::i;:::-;717:139;;;;:::o;862:137::-;907:5;945:6;932:20;923:29;;961:32;987:5;961:32;:::i;:::-;862:137;;;;:::o;1018:338::-;1073:5;1122:3;1115:4;1107:6;1103:17;1099:27;1089:122;;1130:79;;:::i;:::-;1089:122;1247:6;1234:20;1272:78;1346:3;1338:6;1331:4;1323:6;1319:17;1272:78;:::i;:::-;1263:87;;1079:277;1018:338;;;;:::o;1362:139::-;1408:5;1446:6;1433:20;1424:29;;1462:33;1489:5;1462:33;:::i;:::-;1362:139;;;;:::o;1507:135::-;1551:5;1589:6;1576:20;1567:29;;1605:31;1630:5;1605:31;:::i;:::-;1507:135;;;;:::o;1648:329::-;1707:6;1756:2;1744:9;1735:7;1731:23;1727:32;1724:119;;;1762:79;;:::i;:::-;1724:119;1882:1;1907:53;1952:7;1943:6;1932:9;1928:22;1907:53;:::i;:::-;1897:63;;1853:117;1648:329;;;;:::o;1983:351::-;2053:6;2102:2;2090:9;2081:7;2077:23;2073:32;2070:119;;;2108:79;;:::i;:::-;2070:119;2228:1;2253:64;2309:7;2300:6;2289:9;2285:22;2253:64;:::i;:::-;2243:74;;2199:128;1983:351;;;;:::o;2340:474::-;2408:6;2416;2465:2;2453:9;2444:7;2440:23;2436:32;2433:119;;;2471:79;;:::i;:::-;2433:119;2591:1;2616:53;2661:7;2652:6;2641:9;2637:22;2616:53;:::i;:::-;2606:63;;2562:117;2718:2;2744:53;2789:7;2780:6;2769:9;2765:22;2744:53;:::i;:::-;2734:63;;2689:118;2340:474;;;;;:::o;2820:619::-;2897:6;2905;2913;2962:2;2950:9;2941:7;2937:23;2933:32;2930:119;;;2968:79;;:::i;:::-;2930:119;3088:1;3113:53;3158:7;3149:6;3138:9;3134:22;3113:53;:::i;:::-;3103:63;;3059:117;3215:2;3241:53;3286:7;3277:6;3266:9;3262:22;3241:53;:::i;:::-;3231:63;;3186:118;3343:2;3369:53;3414:7;3405:6;3394:9;3390:22;3369:53;:::i;:::-;3359:63;;3314:118;2820:619;;;;;:::o;3445:1267::-;3558:6;3566;3574;3582;3590;3639:3;3627:9;3618:7;3614:23;3610:33;3607:120;;;3646:79;;:::i;:::-;3607:120;3766:1;3791:53;3836:7;3827:6;3816:9;3812:22;3791:53;:::i;:::-;3781:63;;3737:117;3893:2;3919:53;3964:7;3955:6;3944:9;3940:22;3919:53;:::i;:::-;3909:63;;3864:118;4021:2;4047:53;4092:7;4083:6;4072:9;4068:22;4047:53;:::i;:::-;4037:63;;3992:118;4177:2;4166:9;4162:18;4149:32;4208:18;4200:6;4197:30;4194:117;;;4230:79;;:::i;:::-;4194:117;4335:62;4389:7;4380:6;4369:9;4365:22;4335:62;:::i;:::-;4325:72;;4120:287;4474:3;4463:9;4459:19;4446:33;4506:18;4498:6;4495:30;4492:117;;;4528:79;;:::i;:::-;4492:117;4633:62;4687:7;4678:6;4667:9;4663:22;4633:62;:::i;:::-;4623:72;;4417:288;3445:1267;;;;;;;;:::o;4718:474::-;4786:6;4794;4843:2;4831:9;4822:7;4818:23;4814:32;4811:119;;;4849:79;;:::i;:::-;4811:119;4969:1;4994:53;5039:7;5030:6;5019:9;5015:22;4994:53;:::i;:::-;4984:63;;4940:117;5096:2;5122:53;5167:7;5158:6;5147:9;5143:22;5122:53;:::i;:::-;5112:63;;5067:118;4718:474;;;;;:::o;5198:797::-;5284:6;5292;5300;5349:2;5337:9;5328:7;5324:23;5320:32;5317:119;;;5355:79;;:::i;:::-;5317:119;5475:1;5500:53;5545:7;5536:6;5525:9;5521:22;5500:53;:::i;:::-;5490:63;;5446:117;5602:2;5628:53;5673:7;5664:6;5653:9;5649:22;5628:53;:::i;:::-;5618:63;;5573:118;5758:2;5747:9;5743:18;5730:32;5789:18;5781:6;5778:30;5775:117;;;5811:79;;:::i;:::-;5775:117;5916:62;5970:7;5961:6;5950:9;5946:22;5916:62;:::i;:::-;5906:72;;5701:287;5198:797;;;;;:::o;6001:1121::-;6105:6;6113;6121;6129;6178:3;6166:9;6157:7;6153:23;6149:33;6146:120;;;6185:79;;:::i;:::-;6146:120;6305:1;6330:53;6375:7;6366:6;6355:9;6351:22;6330:53;:::i;:::-;6320:63;;6276:117;6432:2;6458:53;6503:7;6494:6;6483:9;6479:22;6458:53;:::i;:::-;6448:63;;6403:118;6588:2;6577:9;6573:18;6560:32;6619:18;6611:6;6608:30;6605:117;;;6641:79;;:::i;:::-;6605:117;6746:62;6800:7;6791:6;6780:9;6776:22;6746:62;:::i;:::-;6736:72;;6531:287;6885:2;6874:9;6870:18;6857:32;6916:18;6908:6;6905:30;6902:117;;;6938:79;;:::i;:::-;6902:117;7043:62;7097:7;7088:6;7077:9;7073:22;7043:62;:::i;:::-;7033:72;;6828:287;6001:1121;;;;;;;:::o;7128:1053::-;7230:6;7238;7246;7254;7262;7270;7319:3;7307:9;7298:7;7294:23;7290:33;7287:120;;;7326:79;;:::i;:::-;7287:120;7446:1;7471:53;7516:7;7507:6;7496:9;7492:22;7471:53;:::i;:::-;7461:63;;7417:117;7573:2;7599:53;7644:7;7635:6;7624:9;7620:22;7599:53;:::i;:::-;7589:63;;7544:118;7701:2;7727:53;7772:7;7763:6;7752:9;7748:22;7727:53;:::i;:::-;7717:63;;7672:118;7829:2;7855:51;7898:7;7889:6;7878:9;7874:22;7855:51;:::i;:::-;7845:61;;7800:116;7955:3;7982:53;8027:7;8018:6;8007:9;8003:22;7982:53;:::i;:::-;7972:63;;7926:119;8084:3;8111:53;8156:7;8147:6;8136:9;8132:22;8111:53;:::i;:::-;8101:63;;8055:119;7128:1053;;;;;;;;:::o;8187:329::-;8246:6;8295:2;8283:9;8274:7;8270:23;8266:32;8263:119;;;8301:79;;:::i;:::-;8263:119;8421:1;8446:53;8491:7;8482:6;8471:9;8467:22;8446:53;:::i;:::-;8436:63;;8392:117;8187:329;;;;:::o;8522:474::-;8590:6;8598;8647:2;8635:9;8626:7;8622:23;8618:32;8615:119;;;8653:79;;:::i;:::-;8615:119;8773:1;8798:53;8843:7;8834:6;8823:9;8819:22;8798:53;:::i;:::-;8788:63;;8744:117;8900:2;8926:53;8971:7;8962:6;8951:9;8947:22;8926:53;:::i;:::-;8916:63;;8871:118;8522:474;;;;;:::o;9002:327::-;9060:6;9109:2;9097:9;9088:7;9084:23;9080:32;9077:119;;;9115:79;;:::i;:::-;9077:119;9235:1;9260:52;9304:7;9295:6;9284:9;9280:22;9260:52;:::i;:::-;9250:62;;9206:116;9002:327;;;;:::o;9335:329::-;9394:6;9443:2;9431:9;9422:7;9418:23;9414:32;9411:119;;;9449:79;;:::i;:::-;9411:119;9569:1;9594:53;9639:7;9630:6;9619:9;9615:22;9594:53;:::i;:::-;9584:63;;9540:117;9335:329;;;;:::o;9670:652::-;9747:6;9755;9804:2;9792:9;9783:7;9779:23;9775:32;9772:119;;;9810:79;;:::i;:::-;9772:119;9930:1;9955:53;10000:7;9991:6;9980:9;9976:22;9955:53;:::i;:::-;9945:63;;9901:117;10085:2;10074:9;10070:18;10057:32;10116:18;10108:6;10105:30;10102:117;;;10138:79;;:::i;:::-;10102:117;10243:62;10297:7;10288:6;10277:9;10273:22;10243:62;:::i;:::-;10233:72;;10028:287;9670:652;;;;;:::o;10328:179::-;10397:10;10418:46;10460:3;10452:6;10418:46;:::i;:::-;10496:4;10491:3;10487:14;10473:28;;10328:179;;;;:::o;10513:108::-;10590:24;10608:5;10590:24;:::i;:::-;10585:3;10578:37;10513:108;;:::o;10627:118::-;10714:24;10732:5;10714:24;:::i;:::-;10709:3;10702:37;10627:118;;:::o;10781:732::-;10900:3;10929:54;10977:5;10929:54;:::i;:::-;10999:86;11078:6;11073:3;10999:86;:::i;:::-;10992:93;;11109:56;11159:5;11109:56;:::i;:::-;11188:7;11219:1;11204:284;11229:6;11226:1;11223:13;11204:284;;;11305:6;11299:13;11332:63;11391:3;11376:13;11332:63;:::i;:::-;11325:70;;11418:60;11471:6;11418:60;:::i;:::-;11408:70;;11264:224;11251:1;11248;11244:9;11239:14;;11204:284;;;11208:14;11504:3;11497:10;;10905:608;;;10781:732;;;;:::o;11519:109::-;11600:21;11615:5;11600:21;:::i;:::-;11595:3;11588:34;11519:109;;:::o;11634:118::-;11721:24;11739:5;11721:24;:::i;:::-;11716:3;11709:37;11634:118;;:::o;11758:157::-;11863:45;11883:24;11901:5;11883:24;:::i;:::-;11863:45;:::i;:::-;11858:3;11851:58;11758:157;;:::o;11921:360::-;12007:3;12035:38;12067:5;12035:38;:::i;:::-;12089:70;12152:6;12147:3;12089:70;:::i;:::-;12082:77;;12168:52;12213:6;12208:3;12201:4;12194:5;12190:16;12168:52;:::i;:::-;12245:29;12267:6;12245:29;:::i;:::-;12240:3;12236:39;12229:46;;12011:270;11921:360;;;;:::o;12287:364::-;12375:3;12403:39;12436:5;12403:39;:::i;:::-;12458:71;12522:6;12517:3;12458:71;:::i;:::-;12451:78;;12538:52;12583:6;12578:3;12571:4;12564:5;12560:16;12538:52;:::i;:::-;12615:29;12637:6;12615:29;:::i;:::-;12610:3;12606:39;12599:46;;12379:272;12287:364;;;;:::o;12657:377::-;12763:3;12791:39;12824:5;12791:39;:::i;:::-;12846:89;12928:6;12923:3;12846:89;:::i;:::-;12839:96;;12944:52;12989:6;12984:3;12977:4;12970:5;12966:16;12944:52;:::i;:::-;13021:6;13016:3;13012:16;13005:23;;12767:267;12657:377;;;;:::o;13040:366::-;13182:3;13203:67;13267:2;13262:3;13203:67;:::i;:::-;13196:74;;13279:93;13368:3;13279:93;:::i;:::-;13397:2;13392:3;13388:12;13381:19;;13040:366;;;:::o;13412:::-;13554:3;13575:67;13639:2;13634:3;13575:67;:::i;:::-;13568:74;;13651:93;13740:3;13651:93;:::i;:::-;13769:2;13764:3;13760:12;13753:19;;13412:366;;;:::o;13784:::-;13926:3;13947:67;14011:2;14006:3;13947:67;:::i;:::-;13940:74;;14023:93;14112:3;14023:93;:::i;:::-;14141:2;14136:3;14132:12;14125:19;;13784:366;;;:::o;14156:::-;14298:3;14319:67;14383:2;14378:3;14319:67;:::i;:::-;14312:74;;14395:93;14484:3;14395:93;:::i;:::-;14513:2;14508:3;14504:12;14497:19;;14156:366;;;:::o;14528:::-;14670:3;14691:67;14755:2;14750:3;14691:67;:::i;:::-;14684:74;;14767:93;14856:3;14767:93;:::i;:::-;14885:2;14880:3;14876:12;14869:19;;14528:366;;;:::o;14900:::-;15042:3;15063:67;15127:2;15122:3;15063:67;:::i;:::-;15056:74;;15139:93;15228:3;15139:93;:::i;:::-;15257:2;15252:3;15248:12;15241:19;;14900:366;;;:::o;15272:::-;15414:3;15435:67;15499:2;15494:3;15435:67;:::i;:::-;15428:74;;15511:93;15600:3;15511:93;:::i;:::-;15629:2;15624:3;15620:12;15613:19;;15272:366;;;:::o;15644:::-;15786:3;15807:67;15871:2;15866:3;15807:67;:::i;:::-;15800:74;;15883:93;15972:3;15883:93;:::i;:::-;16001:2;15996:3;15992:12;15985:19;;15644:366;;;:::o;16016:400::-;16176:3;16197:84;16279:1;16274:3;16197:84;:::i;:::-;16190:91;;16290:93;16379:3;16290:93;:::i;:::-;16408:1;16403:3;16399:11;16392:18;;16016:400;;;:::o;16422:366::-;16564:3;16585:67;16649:2;16644:3;16585:67;:::i;:::-;16578:74;;16661:93;16750:3;16661:93;:::i;:::-;16779:2;16774:3;16770:12;16763:19;;16422:366;;;:::o;16794:::-;16936:3;16957:67;17021:2;17016:3;16957:67;:::i;:::-;16950:74;;17033:93;17122:3;17033:93;:::i;:::-;17151:2;17146:3;17142:12;17135:19;;16794:366;;;:::o;17166:::-;17308:3;17329:67;17393:2;17388:3;17329:67;:::i;:::-;17322:74;;17405:93;17494:3;17405:93;:::i;:::-;17523:2;17518:3;17514:12;17507:19;;17166:366;;;:::o;17538:::-;17680:3;17701:67;17765:2;17760:3;17701:67;:::i;:::-;17694:74;;17777:93;17866:3;17777:93;:::i;:::-;17895:2;17890:3;17886:12;17879:19;;17538:366;;;:::o;17910:::-;18052:3;18073:67;18137:2;18132:3;18073:67;:::i;:::-;18066:74;;18149:93;18238:3;18149:93;:::i;:::-;18267:2;18262:3;18258:12;18251:19;;17910:366;;;:::o;18282:::-;18424:3;18445:67;18509:2;18504:3;18445:67;:::i;:::-;18438:74;;18521:93;18610:3;18521:93;:::i;:::-;18639:2;18634:3;18630:12;18623:19;;18282:366;;;:::o;18654:::-;18796:3;18817:67;18881:2;18876:3;18817:67;:::i;:::-;18810:74;;18893:93;18982:3;18893:93;:::i;:::-;19011:2;19006:3;19002:12;18995:19;;18654:366;;;:::o;19026:::-;19168:3;19189:67;19253:2;19248:3;19189:67;:::i;:::-;19182:74;;19265:93;19354:3;19265:93;:::i;:::-;19383:2;19378:3;19374:12;19367:19;;19026:366;;;:::o;19398:::-;19540:3;19561:67;19625:2;19620:3;19561:67;:::i;:::-;19554:74;;19637:93;19726:3;19637:93;:::i;:::-;19755:2;19750:3;19746:12;19739:19;;19398:366;;;:::o;19770:::-;19912:3;19933:67;19997:2;19992:3;19933:67;:::i;:::-;19926:74;;20009:93;20098:3;20009:93;:::i;:::-;20127:2;20122:3;20118:12;20111:19;;19770:366;;;:::o;20142:::-;20284:3;20305:67;20369:2;20364:3;20305:67;:::i;:::-;20298:74;;20381:93;20470:3;20381:93;:::i;:::-;20499:2;20494:3;20490:12;20483:19;;20142:366;;;:::o;20514:::-;20656:3;20677:67;20741:2;20736:3;20677:67;:::i;:::-;20670:74;;20753:93;20842:3;20753:93;:::i;:::-;20871:2;20866:3;20862:12;20855:19;;20514:366;;;:::o;20886:::-;21028:3;21049:67;21113:2;21108:3;21049:67;:::i;:::-;21042:74;;21125:93;21214:3;21125:93;:::i;:::-;21243:2;21238:3;21234:12;21227:19;;20886:366;;;:::o;21258:::-;21400:3;21421:67;21485:2;21480:3;21421:67;:::i;:::-;21414:74;;21497:93;21586:3;21497:93;:::i;:::-;21615:2;21610:3;21606:12;21599:19;;21258:366;;;:::o;21630:::-;21772:3;21793:67;21857:2;21852:3;21793:67;:::i;:::-;21786:74;;21869:93;21958:3;21869:93;:::i;:::-;21987:2;21982:3;21978:12;21971:19;;21630:366;;;:::o;22002:::-;22144:3;22165:67;22229:2;22224:3;22165:67;:::i;:::-;22158:74;;22241:93;22330:3;22241:93;:::i;:::-;22359:2;22354:3;22350:12;22343:19;;22002:366;;;:::o;22374:402::-;22534:3;22555:85;22637:2;22632:3;22555:85;:::i;:::-;22548:92;;22649:93;22738:3;22649:93;:::i;:::-;22767:2;22762:3;22758:12;22751:19;;22374:402;;;:::o;22782:366::-;22924:3;22945:67;23009:2;23004:3;22945:67;:::i;:::-;22938:74;;23021:93;23110:3;23021:93;:::i;:::-;23139:2;23134:3;23130:12;23123:19;;22782:366;;;:::o;23154:::-;23296:3;23317:67;23381:2;23376:3;23317:67;:::i;:::-;23310:74;;23393:93;23482:3;23393:93;:::i;:::-;23511:2;23506:3;23502:12;23495:19;;23154:366;;;:::o;23526:::-;23668:3;23689:67;23753:2;23748:3;23689:67;:::i;:::-;23682:74;;23765:93;23854:3;23765:93;:::i;:::-;23883:2;23878:3;23874:12;23867:19;;23526:366;;;:::o;23898:402::-;24058:3;24079:85;24161:2;24156:3;24079:85;:::i;:::-;24072:92;;24173:93;24262:3;24173:93;:::i;:::-;24291:2;24286:3;24282:12;24275:19;;23898:402;;;:::o;24306:366::-;24448:3;24469:67;24533:2;24528:3;24469:67;:::i;:::-;24462:74;;24545:93;24634:3;24545:93;:::i;:::-;24663:2;24658:3;24654:12;24647:19;;24306:366;;;:::o;24678:118::-;24765:24;24783:5;24765:24;:::i;:::-;24760:3;24753:37;24678:118;;:::o;24802:112::-;24885:22;24901:5;24885:22;:::i;:::-;24880:3;24873:35;24802:112;;:::o;24920:663::-;25161:3;25183:148;25327:3;25183:148;:::i;:::-;25176:155;;25341:75;25412:3;25403:6;25341:75;:::i;:::-;25441:2;25436:3;25432:12;25425:19;;25454:75;25525:3;25516:6;25454:75;:::i;:::-;25554:2;25549:3;25545:12;25538:19;;25574:3;25567:10;;24920:663;;;;;:::o;25589:967::-;25971:3;25993:148;26137:3;25993:148;:::i;:::-;25986:155;;26158:95;26249:3;26240:6;26158:95;:::i;:::-;26151:102;;26270:148;26414:3;26270:148;:::i;:::-;26263:155;;26435:95;26526:3;26517:6;26435:95;:::i;:::-;26428:102;;26547:3;26540:10;;25589:967;;;;;:::o;26562:222::-;26655:4;26693:2;26682:9;26678:18;26670:26;;26706:71;26774:1;26763:9;26759:17;26750:6;26706:71;:::i;:::-;26562:222;;;;:::o;26790:949::-;27059:4;27097:3;27086:9;27082:19;27074:27;;27111:71;27179:1;27168:9;27164:17;27155:6;27111:71;:::i;:::-;27192:72;27260:2;27249:9;27245:18;27236:6;27192:72;:::i;:::-;27274;27342:2;27331:9;27327:18;27318:6;27274:72;:::i;:::-;27356;27424:2;27413:9;27409:18;27400:6;27356:72;:::i;:::-;27476:9;27470:4;27466:20;27460:3;27449:9;27445:19;27438:49;27504:76;27575:4;27566:6;27504:76;:::i;:::-;27496:84;;27628:9;27622:4;27618:20;27612:3;27601:9;27597:19;27590:49;27656:76;27727:4;27718:6;27656:76;:::i;:::-;27648:84;;26790:949;;;;;;;;;:::o;27745:332::-;27866:4;27904:2;27893:9;27889:18;27881:26;;27917:71;27985:1;27974:9;27970:17;27961:6;27917:71;:::i;:::-;27998:72;28066:2;28055:9;28051:18;28042:6;27998:72;:::i;:::-;27745:332;;;;;:::o;28083:373::-;28226:4;28264:2;28253:9;28249:18;28241:26;;28313:9;28307:4;28303:20;28299:1;28288:9;28284:17;28277:47;28341:108;28444:4;28435:6;28341:108;:::i;:::-;28333:116;;28083:373;;;;:::o;28462:210::-;28549:4;28587:2;28576:9;28572:18;28564:26;;28600:65;28662:1;28651:9;28647:17;28638:6;28600:65;:::i;:::-;28462:210;;;;:::o;28678:222::-;28771:4;28809:2;28798:9;28794:18;28786:26;;28822:71;28890:1;28879:9;28875:17;28866:6;28822:71;:::i;:::-;28678:222;;;;:::o;28906:553::-;29083:4;29121:3;29110:9;29106:19;29098:27;;29135:71;29203:1;29192:9;29188:17;29179:6;29135:71;:::i;:::-;29216:72;29284:2;29273:9;29269:18;29260:6;29216:72;:::i;:::-;29298;29366:2;29355:9;29351:18;29342:6;29298:72;:::i;:::-;29380;29448:2;29437:9;29433:18;29424:6;29380:72;:::i;:::-;28906:553;;;;;;;:::o;29465:664::-;29670:4;29708:3;29697:9;29693:19;29685:27;;29722:71;29790:1;29779:9;29775:17;29766:6;29722:71;:::i;:::-;29803:72;29871:2;29860:9;29856:18;29847:6;29803:72;:::i;:::-;29885;29953:2;29942:9;29938:18;29929:6;29885:72;:::i;:::-;29967;30035:2;30024:9;30020:18;30011:6;29967:72;:::i;:::-;30049:73;30117:3;30106:9;30102:19;30093:6;30049:73;:::i;:::-;29465:664;;;;;;;;:::o;30135:545::-;30308:4;30346:3;30335:9;30331:19;30323:27;;30360:71;30428:1;30417:9;30413:17;30404:6;30360:71;:::i;:::-;30441:68;30505:2;30494:9;30490:18;30481:6;30441:68;:::i;:::-;30519:72;30587:2;30576:9;30572:18;30563:6;30519:72;:::i;:::-;30601;30669:2;30658:9;30654:18;30645:6;30601:72;:::i;:::-;30135:545;;;;;;;:::o;30686:313::-;30799:4;30837:2;30826:9;30822:18;30814:26;;30886:9;30880:4;30876:20;30872:1;30861:9;30857:17;30850:47;30914:78;30987:4;30978:6;30914:78;:::i;:::-;30906:86;;30686:313;;;;:::o;31005:419::-;31171:4;31209:2;31198:9;31194:18;31186:26;;31258:9;31252:4;31248:20;31244:1;31233:9;31229:17;31222:47;31286:131;31412:4;31286:131;:::i;:::-;31278:139;;31005:419;;;:::o;31430:::-;31596:4;31634:2;31623:9;31619:18;31611:26;;31683:9;31677:4;31673:20;31669:1;31658:9;31654:17;31647:47;31711:131;31837:4;31711:131;:::i;:::-;31703:139;;31430:419;;;:::o;31855:::-;32021:4;32059:2;32048:9;32044:18;32036:26;;32108:9;32102:4;32098:20;32094:1;32083:9;32079:17;32072:47;32136:131;32262:4;32136:131;:::i;:::-;32128:139;;31855:419;;;:::o;32280:::-;32446:4;32484:2;32473:9;32469:18;32461:26;;32533:9;32527:4;32523:20;32519:1;32508:9;32504:17;32497:47;32561:131;32687:4;32561:131;:::i;:::-;32553:139;;32280:419;;;:::o;32705:::-;32871:4;32909:2;32898:9;32894:18;32886:26;;32958:9;32952:4;32948:20;32944:1;32933:9;32929:17;32922:47;32986:131;33112:4;32986:131;:::i;:::-;32978:139;;32705:419;;;:::o;33130:::-;33296:4;33334:2;33323:9;33319:18;33311:26;;33383:9;33377:4;33373:20;33369:1;33358:9;33354:17;33347:47;33411:131;33537:4;33411:131;:::i;:::-;33403:139;;33130:419;;;:::o;33555:::-;33721:4;33759:2;33748:9;33744:18;33736:26;;33808:9;33802:4;33798:20;33794:1;33783:9;33779:17;33772:47;33836:131;33962:4;33836:131;:::i;:::-;33828:139;;33555:419;;;:::o;33980:::-;34146:4;34184:2;34173:9;34169:18;34161:26;;34233:9;34227:4;34223:20;34219:1;34208:9;34204:17;34197:47;34261:131;34387:4;34261:131;:::i;:::-;34253:139;;33980:419;;;:::o;34405:::-;34571:4;34609:2;34598:9;34594:18;34586:26;;34658:9;34652:4;34648:20;34644:1;34633:9;34629:17;34622:47;34686:131;34812:4;34686:131;:::i;:::-;34678:139;;34405:419;;;:::o;34830:::-;34996:4;35034:2;35023:9;35019:18;35011:26;;35083:9;35077:4;35073:20;35069:1;35058:9;35054:17;35047:47;35111:131;35237:4;35111:131;:::i;:::-;35103:139;;34830:419;;;:::o;35255:::-;35421:4;35459:2;35448:9;35444:18;35436:26;;35508:9;35502:4;35498:20;35494:1;35483:9;35479:17;35472:47;35536:131;35662:4;35536:131;:::i;:::-;35528:139;;35255:419;;;:::o;35680:::-;35846:4;35884:2;35873:9;35869:18;35861:26;;35933:9;35927:4;35923:20;35919:1;35908:9;35904:17;35897:47;35961:131;36087:4;35961:131;:::i;:::-;35953:139;;35680:419;;;:::o;36105:::-;36271:4;36309:2;36298:9;36294:18;36286:26;;36358:9;36352:4;36348:20;36344:1;36333:9;36329:17;36322:47;36386:131;36512:4;36386:131;:::i;:::-;36378:139;;36105:419;;;:::o;36530:::-;36696:4;36734:2;36723:9;36719:18;36711:26;;36783:9;36777:4;36773:20;36769:1;36758:9;36754:17;36747:47;36811:131;36937:4;36811:131;:::i;:::-;36803:139;;36530:419;;;:::o;36955:::-;37121:4;37159:2;37148:9;37144:18;37136:26;;37208:9;37202:4;37198:20;37194:1;37183:9;37179:17;37172:47;37236:131;37362:4;37236:131;:::i;:::-;37228:139;;36955:419;;;:::o;37380:::-;37546:4;37584:2;37573:9;37569:18;37561:26;;37633:9;37627:4;37623:20;37619:1;37608:9;37604:17;37597:47;37661:131;37787:4;37661:131;:::i;:::-;37653:139;;37380:419;;;:::o;37805:::-;37971:4;38009:2;37998:9;37994:18;37986:26;;38058:9;38052:4;38048:20;38044:1;38033:9;38029:17;38022:47;38086:131;38212:4;38086:131;:::i;:::-;38078:139;;37805:419;;;:::o;38230:::-;38396:4;38434:2;38423:9;38419:18;38411:26;;38483:9;38477:4;38473:20;38469:1;38458:9;38454:17;38447:47;38511:131;38637:4;38511:131;:::i;:::-;38503:139;;38230:419;;;:::o;38655:::-;38821:4;38859:2;38848:9;38844:18;38836:26;;38908:9;38902:4;38898:20;38894:1;38883:9;38879:17;38872:47;38936:131;39062:4;38936:131;:::i;:::-;38928:139;;38655:419;;;:::o;39080:::-;39246:4;39284:2;39273:9;39269:18;39261:26;;39333:9;39327:4;39323:20;39319:1;39308:9;39304:17;39297:47;39361:131;39487:4;39361:131;:::i;:::-;39353:139;;39080:419;;;:::o;39505:::-;39671:4;39709:2;39698:9;39694:18;39686:26;;39758:9;39752:4;39748:20;39744:1;39733:9;39729:17;39722:47;39786:131;39912:4;39786:131;:::i;:::-;39778:139;;39505:419;;;:::o;39930:::-;40096:4;40134:2;40123:9;40119:18;40111:26;;40183:9;40177:4;40173:20;40169:1;40158:9;40154:17;40147:47;40211:131;40337:4;40211:131;:::i;:::-;40203:139;;39930:419;;;:::o;40355:::-;40521:4;40559:2;40548:9;40544:18;40536:26;;40608:9;40602:4;40598:20;40594:1;40583:9;40579:17;40572:47;40636:131;40762:4;40636:131;:::i;:::-;40628:139;;40355:419;;;:::o;40780:::-;40946:4;40984:2;40973:9;40969:18;40961:26;;41033:9;41027:4;41023:20;41019:1;41008:9;41004:17;40997:47;41061:131;41187:4;41061:131;:::i;:::-;41053:139;;40780:419;;;:::o;41205:::-;41371:4;41409:2;41398:9;41394:18;41386:26;;41458:9;41452:4;41448:20;41444:1;41433:9;41429:17;41422:47;41486:131;41612:4;41486:131;:::i;:::-;41478:139;;41205:419;;;:::o;41630:::-;41796:4;41834:2;41823:9;41819:18;41811:26;;41883:9;41877:4;41873:20;41869:1;41858:9;41854:17;41847:47;41911:131;42037:4;41911:131;:::i;:::-;41903:139;;41630:419;;;:::o;42055:::-;42221:4;42259:2;42248:9;42244:18;42236:26;;42308:9;42302:4;42298:20;42294:1;42283:9;42279:17;42272:47;42336:131;42462:4;42336:131;:::i;:::-;42328:139;;42055:419;;;:::o;42480:::-;42646:4;42684:2;42673:9;42669:18;42661:26;;42733:9;42727:4;42723:20;42719:1;42708:9;42704:17;42697:47;42761:131;42887:4;42761:131;:::i;:::-;42753:139;;42480:419;;;:::o;42905:222::-;42998:4;43036:2;43025:9;43021:18;43013:26;;43049:71;43117:1;43106:9;43102:17;43093:6;43049:71;:::i;:::-;42905:222;;;;:::o;43133:616::-;43318:4;43356:2;43345:9;43341:18;43333:26;;43369:71;43437:1;43426:9;43422:17;43413:6;43369:71;:::i;:::-;43487:9;43481:4;43477:20;43472:2;43461:9;43457:18;43450:48;43515:76;43586:4;43577:6;43515:76;:::i;:::-;43507:84;;43638:9;43632:4;43628:20;43623:2;43612:9;43608:18;43601:48;43666:76;43737:4;43728:6;43666:76;:::i;:::-;43658:84;;43133:616;;;;;;:::o;43755:332::-;43876:4;43914:2;43903:9;43899:18;43891:26;;43927:71;43995:1;43984:9;43980:17;43971:6;43927:71;:::i;:::-;44008:72;44076:2;44065:9;44061:18;44052:6;44008:72;:::i;:::-;43755:332;;;;;:::o;44093:214::-;44182:4;44220:2;44209:9;44205:18;44197:26;;44233:67;44297:1;44286:9;44282:17;44273:6;44233:67;:::i;:::-;44093:214;;;;:::o;44313:129::-;44347:6;44374:20;;:::i;:::-;44364:30;;44403:33;44431:4;44423:6;44403:33;:::i;:::-;44313:129;;;:::o;44448:75::-;44481:6;44514:2;44508:9;44498:19;;44448:75;:::o;44529:307::-;44590:4;44680:18;44672:6;44669:30;44666:56;;;44702:18;;:::i;:::-;44666:56;44740:29;44762:6;44740:29;:::i;:::-;44732:37;;44824:4;44818;44814:15;44806:23;;44529:307;;;:::o;44842:132::-;44909:4;44932:3;44924:11;;44962:4;44957:3;44953:14;44945:22;;44842:132;;;:::o;44980:114::-;45047:6;45081:5;45075:12;45065:22;;44980:114;;;:::o;45100:98::-;45151:6;45185:5;45179:12;45169:22;;45100:98;;;:::o;45204:99::-;45256:6;45290:5;45284:12;45274:22;;45204:99;;;:::o;45309:113::-;45379:4;45411;45406:3;45402:14;45394:22;;45309:113;;;:::o;45428:184::-;45527:11;45561:6;45556:3;45549:19;45601:4;45596:3;45592:14;45577:29;;45428:184;;;;:::o;45618:168::-;45701:11;45735:6;45730:3;45723:19;45775:4;45770:3;45766:14;45751:29;;45618:168;;;;:::o;45792:169::-;45876:11;45910:6;45905:3;45898:19;45950:4;45945:3;45941:14;45926:29;;45792:169;;;;:::o;45967:148::-;46069:11;46106:3;46091:18;;45967:148;;;;:::o;46121:305::-;46161:3;46180:20;46198:1;46180:20;:::i;:::-;46175:25;;46214:20;46232:1;46214:20;:::i;:::-;46209:25;;46368:1;46300:66;46296:74;46293:1;46290:81;46287:107;;;46374:18;;:::i;:::-;46287:107;46418:1;46415;46411:9;46404:16;;46121:305;;;;:::o;46432:185::-;46472:1;46489:20;46507:1;46489:20;:::i;:::-;46484:25;;46523:20;46541:1;46523:20;:::i;:::-;46518:25;;46562:1;46552:35;;46567:18;;:::i;:::-;46552:35;46609:1;46606;46602:9;46597:14;;46432:185;;;;:::o;46623:348::-;46663:7;46686:20;46704:1;46686:20;:::i;:::-;46681:25;;46720:20;46738:1;46720:20;:::i;:::-;46715:25;;46908:1;46840:66;46836:74;46833:1;46830:81;46825:1;46818:9;46811:17;46807:105;46804:131;;;46915:18;;:::i;:::-;46804:131;46963:1;46960;46956:9;46945:20;;46623:348;;;;:::o;46977:191::-;47017:4;47037:20;47055:1;47037:20;:::i;:::-;47032:25;;47071:20;47089:1;47071:20;:::i;:::-;47066:25;;47110:1;47107;47104:8;47101:34;;;47115:18;;:::i;:::-;47101:34;47160:1;47157;47153:9;47145:17;;46977:191;;;;:::o;47174:96::-;47211:7;47240:24;47258:5;47240:24;:::i;:::-;47229:35;;47174:96;;;:::o;47276:90::-;47310:7;47353:5;47346:13;47339:21;47328:32;;47276:90;;;:::o;47372:77::-;47409:7;47438:5;47427:16;;47372:77;;;:::o;47455:149::-;47491:7;47531:66;47524:5;47520:78;47509:89;;47455:149;;;:::o;47610:126::-;47647:7;47687:42;47680:5;47676:54;47665:65;;47610:126;;;:::o;47742:77::-;47779:7;47808:5;47797:16;;47742:77;;;:::o;47825:86::-;47860:7;47900:4;47893:5;47889:16;47878:27;;47825:86;;;:::o;47917:154::-;48001:6;47996:3;47991;47978:30;48063:1;48054:6;48049:3;48045:16;48038:27;47917:154;;;:::o;48077:307::-;48145:1;48155:113;48169:6;48166:1;48163:13;48155:113;;;48254:1;48249:3;48245:11;48239:18;48235:1;48230:3;48226:11;48219:39;48191:2;48188:1;48184:10;48179:15;;48155:113;;;48286:6;48283:1;48280:13;48277:101;;;48366:1;48357:6;48352:3;48348:16;48341:27;48277:101;48126:258;48077:307;;;:::o;48390:171::-;48429:3;48452:24;48470:5;48452:24;:::i;:::-;48443:33;;48498:4;48491:5;48488:15;48485:41;;;48506:18;;:::i;:::-;48485:41;48553:1;48546:5;48542:13;48535:20;;48390:171;;;:::o;48567:320::-;48611:6;48648:1;48642:4;48638:12;48628:22;;48695:1;48689:4;48685:12;48716:18;48706:81;;48772:4;48764:6;48760:17;48750:27;;48706:81;48834:2;48826:6;48823:14;48803:18;48800:38;48797:84;;;48853:18;;:::i;:::-;48797:84;48618:269;48567:320;;;:::o;48893:281::-;48976:27;48998:4;48976:27;:::i;:::-;48968:6;48964:40;49106:6;49094:10;49091:22;49070:18;49058:10;49055:34;49052:62;49049:88;;;49117:18;;:::i;:::-;49049:88;49157:10;49153:2;49146:22;48936:238;48893:281;;:::o;49180:79::-;49219:7;49248:5;49237:16;;49180:79;;;:::o;49265:180::-;49313:77;49310:1;49303:88;49410:4;49407:1;49400:15;49434:4;49431:1;49424:15;49451:180;49499:77;49496:1;49489:88;49596:4;49593:1;49586:15;49620:4;49617:1;49610:15;49637:180;49685:77;49682:1;49675:88;49782:4;49779:1;49772:15;49806:4;49803:1;49796:15;49823:180;49871:77;49868:1;49861:88;49968:4;49965:1;49958:15;49992:4;49989:1;49982:15;50009:180;50057:77;50054:1;50047:88;50154:4;50151:1;50144:15;50178:4;50175:1;50168:15;50195:180;50243:77;50240:1;50233:88;50340:4;50337:1;50330:15;50364:4;50361:1;50354:15;50381:117;50490:1;50487;50480:12;50504:117;50613:1;50610;50603:12;50627:117;50736:1;50733;50726:12;50750:117;50859:1;50856;50849:12;50873:102;50914:6;50965:2;50961:7;50956:2;50949:5;50945:14;50941:28;50931:38;;50873:102;;;:::o;50981:174::-;51121:26;51117:1;51109:6;51105:14;51098:50;50981:174;:::o;51161:182::-;51301:34;51297:1;51289:6;51285:14;51278:58;51161:182;:::o;51349:175::-;51489:27;51485:1;51477:6;51473:14;51466:51;51349:175;:::o;51530:170::-;51670:22;51666:1;51658:6;51654:14;51647:46;51530:170;:::o;51706:224::-;51846:34;51842:1;51834:6;51830:14;51823:58;51915:7;51910:2;51902:6;51898:15;51891:32;51706:224;:::o;51936:170::-;52076:22;52072:1;52064:6;52060:14;52053:46;51936:170;:::o;52112:181::-;52252:33;52248:1;52240:6;52236:14;52229:57;52112:181;:::o;52299:226::-;52439:34;52435:1;52427:6;52423:14;52416:58;52508:9;52503:2;52495:6;52491:15;52484:34;52299:226;:::o;52531:214::-;52671:66;52667:1;52659:6;52655:14;52648:90;52531:214;:::o;52751:221::-;52891:34;52887:1;52879:6;52875:14;52868:58;52960:4;52955:2;52947:6;52943:15;52936:29;52751:221;:::o;52978:180::-;53118:32;53114:1;53106:6;53102:14;53095:56;52978:180;:::o;53164:223::-;53304:34;53300:1;53292:6;53288:14;53281:58;53373:6;53368:2;53360:6;53356:15;53349:31;53164:223;:::o;53393:221::-;53533:34;53529:1;53521:6;53517:14;53510:58;53602:4;53597:2;53589:6;53585:15;53578:29;53393:221;:::o;53620:182::-;53760:34;53756:1;53748:6;53744:14;53737:58;53620:182;:::o;53808:220::-;53948:34;53944:1;53936:6;53932:14;53925:58;54017:3;54012:2;54004:6;54000:15;53993:28;53808:220;:::o;54034:166::-;54174:18;54170:1;54162:6;54158:14;54151:42;54034:166;:::o;54206:174::-;54346:26;54342:1;54334:6;54330:14;54323:50;54206:174;:::o;54386:176::-;54526:28;54522:1;54514:6;54510:14;54503:52;54386:176;:::o;54568:221::-;54708:34;54704:1;54696:6;54692:14;54685:58;54777:4;54772:2;54764:6;54760:15;54753:29;54568:221;:::o;54795:182::-;54935:34;54931:1;54923:6;54919:14;54912:58;54795:182;:::o;54983:226::-;55123:34;55119:1;55111:6;55107:14;55100:58;55192:9;55187:2;55179:6;55175:15;55168:34;54983:226;:::o;55215:301::-;55355:34;55351:1;55343:6;55339:14;55332:58;55424:34;55419:2;55411:6;55407:15;55400:59;55493:15;55488:2;55480:6;55476:15;55469:40;55215:301;:::o;55522:223::-;55662:34;55658:1;55650:6;55646:14;55639:58;55731:6;55726:2;55718:6;55714:15;55707:31;55522:223;:::o;55751:225::-;55891:34;55887:1;55879:6;55875:14;55868:58;55960:8;55955:2;55947:6;55943:15;55936:33;55751:225;:::o;55982:231::-;56122:34;56118:1;56110:6;56106:14;56099:58;56191:14;56186:2;56178:6;56174:15;56167:39;55982:231;:::o;56219:173::-;56359:25;56355:1;56347:6;56343:14;56336:49;56219:173;:::o;56398:225::-;56538:34;56534:1;56526:6;56522:14;56515:58;56607:8;56602:2;56594:6;56590:15;56583:33;56398:225;:::o;56629:222::-;56769:34;56765:1;56757:6;56753:14;56746:58;56838:5;56833:2;56825:6;56821:15;56814:30;56629:222;:::o;56857:::-;56997:34;56993:1;56985:6;56981:14;56974:58;57066:5;57061:2;57053:6;57049:15;57042:30;56857:222;:::o;57085:167::-;57225:19;57221:1;57213:6;57209:14;57202:43;57085:167;:::o;57258:234::-;57398:34;57394:1;57386:6;57382:14;57375:58;57467:17;57462:2;57454:6;57450:15;57443:42;57258:234;:::o;57498:122::-;57571:24;57589:5;57571:24;:::i;:::-;57564:5;57561:35;57551:63;;57610:1;57607;57600:12;57551:63;57498:122;:::o;57626:::-;57699:24;57717:5;57699:24;:::i;:::-;57692:5;57689:35;57679:63;;57738:1;57735;57728:12;57679:63;57626:122;:::o;57754:120::-;57826:23;57843:5;57826:23;:::i;:::-;57819:5;57816:34;57806:62;;57864:1;57861;57854:12;57806:62;57754:120;:::o;57880:122::-;57953:24;57971:5;57953:24;:::i;:::-;57946:5;57943:35;57933:63;;57992:1;57989;57982:12;57933:63;57880:122;:::o;58008:118::-;58079:22;58095:5;58079:22;:::i;:::-;58072:5;58069:33;58059:61;;58116:1;58113;58106:12;58059:61;58008:118;:::o

Swarm Source

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