ETH Price: $3,039.32 (-3.72%)

Token

NOVAMOON (NOMO)

Overview

Max Total Supply

99,999,999,999.999999999996999997 NOMO

Holders

11

Market

Price

$0.00 @ 0.000000 ETH

Onchain Market Cap

-

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
Arbitrum: ArbOS
Balance
74,577,765 NOMO

Value
$0.00
0x00000000000000000000000000000000000a4b05
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
Token

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Nova.Arbiscan.io on 2023-03-27
*/

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


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

pragma solidity ^0.8.0;

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

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


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

pragma solidity ^0.8.0;


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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

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

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

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

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

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


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

pragma solidity ^0.8.0;



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

    /**
     * @dev Searches a sorted `array` and returns the first index that contains
     * a value greater or equal to `element`. If no such index exists (i.e. all
     * values in the array are strictly less than `element`), the array length is
     * returned. Time complexity O(log n).
     *
     * `array` is expected to be sorted in ascending order, and to contain no
     * repeated elements.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        if (array.length == 0) {
            return 0;
        }

        uint256 low = 0;
        uint256 high = array.length;

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds down (it does integer division with truncation).
            if (unsafeAccess(array, mid).value > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && unsafeAccess(array, low - 1).value == element) {
            return low - 1;
        } else {
            return low;
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
        bytes32 slot;
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getAddressSlot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
        bytes32 slot;
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getBytes32Slot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
        bytes32 slot;
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getUint256Slot();
    }
}

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


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

pragma solidity ^0.8.0;

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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


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

pragma solidity ^0.8.0;




/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

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

        _beforeTokenTransfer(from, to, amount);

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

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;




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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;




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

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

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

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

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

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

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

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

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

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

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

        return snapshotted ? value : balanceOf(account);
    }

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

        return snapshotted ? value : totalSupply();
    }

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;



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

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

// File: NOVAMOON.sol


pragma solidity >=0.7.0 <= 0.9.0;






/// @custom:security-contact 
contract Token is ERC20, ERC20Burnable, ERC20Snapshot, Ownable, ERC20FlashMint {
    constructor() ERC20("NOVAMOON", "NOMO") {
        _mint(msg.sender, 100000000000 * 10 ** decimals());
    }

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

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

    // The following functions are overrides required by Solidity.

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

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Snapshot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"flashFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC3156FlashBorrower","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"maxFlashLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"snapshot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040518060400160405280600881526020017f4e4f56414d4f4f4e0000000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f4e4f4d4f0000000000000000000000000000000000000000000000000000000081525081600390816200008f9190620008cd565b508060049081620000a19190620008cd565b505050620000c4620000b86200010b60201b60201c565b6200011360201b60201c565b6200010533620000d9620001d960201b60201c565b600a620000e7919062000b44565b64174876e800620000f9919062000b95565b620001e260201b60201c565b62000d36565b600033905090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60006012905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000254576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024b9062000c41565b60405180910390fd5b62000268600083836200034f60201b60201c565b80600260008282546200027c919062000c63565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516200032f919062000caf565b60405180910390a36200034b600083836200036c60201b60201c565b5050565b620003678383836200037160201b62000c7a1760201c565b505050565b505050565b620003898383836200046a60201b62000d321760201c565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603620003e557620003cf826200046f60201b60201c565b620003df620004d260201b60201c565b62000465565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000441576200042b836200046f60201b60201c565b6200043b620004d260201b60201c565b62000464565b62000452836200046f60201b60201c565b62000463826200046f60201b60201c565b5b5b505050565b505050565b620004cf600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020620004c383620004f660201b60201c565b6200053e60201b60201c565b50565b620004f46006620004e8620005ca60201b60201c565b6200053e60201b60201c565b565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600062000550620005d460201b60201c565b9050806200056784600001620005f260201b60201c565b1015620005c55782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b6000600254905090565b6000620005ed60086200064560201b62000d371760201c565b905090565b6000808280549050036200060a576000905062000640565b81600183805490506200061e919062000ccc565b8154811062000632576200063162000d07565b5b906000526020600020015490505b919050565b600081600001549050919050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620006d557607f821691505b602082108103620006eb57620006ea6200068d565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620007557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000716565b62000761868362000716565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620007ae620007a8620007a28462000779565b62000783565b62000779565b9050919050565b6000819050919050565b620007ca836200078d565b620007e2620007d982620007b5565b84845462000723565b825550505050565b600090565b620007f9620007ea565b62000806818484620007bf565b505050565b5b818110156200082e5762000822600082620007ef565b6001810190506200080c565b5050565b601f8211156200087d576200084781620006f1565b620008528462000706565b8101602085101562000862578190505b6200087a620008718562000706565b8301826200080b565b50505b505050565b600082821c905092915050565b6000620008a26000198460080262000882565b1980831691505092915050565b6000620008bd83836200088f565b9150826002028217905092915050565b620008d88262000653565b67ffffffffffffffff811115620008f457620008f36200065e565b5b620009008254620006bc565b6200090d82828562000832565b600060209050601f83116001811462000945576000841562000930578287015190505b6200093c8582620008af565b865550620009ac565b601f1984166200095586620006f1565b60005b828110156200097f5784890151825560018201915060208501945060208101905062000958565b868310156200099f57848901516200099b601f8916826200088f565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b600185111562000a425780860481111562000a1a5762000a19620009b4565b5b600185161562000a2a5780820291505b808102905062000a3a85620009e3565b9450620009fa565b94509492505050565b60008262000a5d576001905062000b30565b8162000a6d576000905062000b30565b816001811462000a86576002811462000a915762000ac7565b600191505062000b30565b60ff84111562000aa65762000aa5620009b4565b5b8360020a91508482111562000ac05762000abf620009b4565b5b5062000b30565b5060208310610133831016604e8410600b841016171562000b015782820a90508381111562000afb5762000afa620009b4565b5b62000b30565b62000b108484846001620009f0565b9250905081840481111562000b2a5762000b29620009b4565b5b81810290505b9392505050565b600060ff82169050919050565b600062000b518262000779565b915062000b5e8362000b37565b925062000b8d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848462000a4b565b905092915050565b600062000ba28262000779565b915062000baf8362000779565b925082820262000bbf8162000779565b9150828204841483151762000bd95762000bd8620009b4565b5b5092915050565b600082825260208201905092915050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b600062000c29601f8362000be0565b915062000c368262000bf1565b602082019050919050565b6000602082019050818103600083015262000c5c8162000c1a565b9050919050565b600062000c708262000779565b915062000c7d8362000779565b925082820190508082111562000c985762000c97620009b4565b5b92915050565b62000ca98162000779565b82525050565b600060208201905062000cc6600083018462000c9e565b92915050565b600062000cd98262000779565b915062000ce68362000779565b925082820390508181111562000d015762000d00620009b4565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b612a4b8062000d466000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806370a08231116100c3578063981b24d01161007c578063981b24d0146103a0578063a457c2d7146103d0578063a9059cbb14610400578063d9d98ce414610430578063dd62ed3e14610460578063f2fde38b146104905761014d565b806370a0823114610304578063715018a61461033457806379cc67901461033e5780638da5cb5b1461035a57806395d89b41146103785780639711715a146103965761014d565b80633950935111610115578063395093511461020c57806340c10f191461023c57806342966c68146102585780634ee2cd7e146102745780635cffe9de146102a4578063613255ab146102d45761014d565b806306fdde0314610152578063095ea7b31461017057806318160ddd146101a057806323b872dd146101be578063313ce567146101ee575b600080fd5b61015a6104ac565b6040516101679190611adc565b60405180910390f35b61018a60048036038101906101859190611b9c565b61053e565b6040516101979190611bf7565b60405180910390f35b6101a8610561565b6040516101b59190611c21565b60405180910390f35b6101d860048036038101906101d39190611c3c565b61056b565b6040516101e59190611bf7565b60405180910390f35b6101f661059a565b6040516102039190611cab565b60405180910390f35b61022660048036038101906102219190611b9c565b6105a3565b6040516102339190611bf7565b60405180910390f35b61025660048036038101906102519190611b9c565b6105da565b005b610272600480360381019061026d9190611cc6565b6105f0565b005b61028e60048036038101906102899190611b9c565b610604565b60405161029b9190611c21565b60405180910390f35b6102be60048036038101906102b99190611d96565b610674565b6040516102cb9190611bf7565b60405180910390f35b6102ee60048036038101906102e99190611e1e565b610861565b6040516102fb9190611c21565b60405180910390f35b61031e60048036038101906103199190611e1e565b6108d8565b60405161032b9190611c21565b60405180910390f35b61033c610920565b005b61035860048036038101906103539190611b9c565b610934565b005b610362610954565b60405161036f9190611e5a565b60405180910390f35b61038061097e565b60405161038d9190611adc565b60405180910390f35b61039e610a10565b005b6103ba60048036038101906103b59190611cc6565b610a23565b6040516103c79190611c21565b60405180910390f35b6103ea60048036038101906103e59190611b9c565b610a54565b6040516103f79190611bf7565b60405180910390f35b61041a60048036038101906104159190611b9c565b610acb565b6040516104279190611bf7565b60405180910390f35b61044a60048036038101906104459190611b9c565b610aee565b6040516104579190611c21565b60405180910390f35b61047a60048036038101906104759190611e75565b610b70565b6040516104879190611c21565b60405180910390f35b6104aa60048036038101906104a59190611e1e565b610bf7565b005b6060600380546104bb90611ee4565b80601f01602080910402602001604051908101604052809291908181526020018280546104e790611ee4565b80156105345780601f1061050957610100808354040283529160200191610534565b820191906000526020600020905b81548152906001019060200180831161051757829003601f168201915b5050505050905090565b600080610549610d45565b9050610556818585610d4d565b600191505092915050565b6000600254905090565b600080610576610d45565b9050610583858285610f16565b61058e858585610fa2565b60019150509392505050565b60006012905090565b6000806105ae610d45565b90506105cf8185856105c08589610b70565b6105ca9190611f44565b610d4d565b600191505092915050565b6105e2611218565b6105ec8282611296565b5050565b6106016105fb610d45565b826113ec565b50565b600080600061065184600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206115b9565b915091508161066857610663856108d8565b61066a565b805b9250505092915050565b600061067f85610861565b8411156106c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b890611fea565b60405180910390fd5b60006106cd8686610aee565b90506106d98786611296565b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd98773ffffffffffffffffffffffffffffffffffffffff166323e30c8b338989868a8a6040518763ffffffff1660e01b815260040161073d96959493929190612057565b6020604051808303816000875af115801561075c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078091906120e9565b146107c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b790612188565b60405180910390fd5b60006107ca6116ae565b90506107e2883084896107dd9190611f44565b610f16565b600082148061081d5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b1561083c576108378883886108329190611f44565b6113ec565b610852565b61084688876113ec565b610851888284610fa2565b5b60019250505095945050505050565b60003073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461089d5760006108d1565b6108a5610561565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6108d091906121a8565b5b9050919050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610928611218565b61093260006116b3565b565b61094682610940610d45565b83610f16565b61095082826113ec565b5050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606004805461098d90611ee4565b80601f01602080910402602001604051908101604052809291908181526020018280546109b990611ee4565b8015610a065780601f106109db57610100808354040283529160200191610a06565b820191906000526020600020905b8154815290600101906020018083116109e957829003601f168201915b5050505050905090565b610a18611218565b610a20611779565b50565b6000806000610a338460066115b9565b9150915081610a4957610a44610561565b610a4b565b805b92505050919050565b600080610a5f610d45565b90506000610a6d8286610b70565b905083811015610ab2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa99061224e565b60405180910390fd5b610abf8286868403610d4d565b60019250505092915050565b600080610ad6610d45565b9050610ae3818585610fa2565b600191505092915050565b60003073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610b5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b55906122ba565b60405180910390fd5b610b6883836117cf565b905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610bff611218565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c659061234c565b60405180910390fd5b610c77816116b3565b50565b610c85838383610d32565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ccf57610cc2826117d7565b610cca61182a565b610d2d565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d1957610d0c836117d7565b610d1461182a565b610d2c565b610d22836117d7565b610d2b826117d7565b5b5b505050565b505050565b600081600001549050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610dbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db3906123de565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2290612470565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051610f099190611c21565b60405180910390a3505050565b6000610f228484610b70565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610f9c5781811015610f8e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f85906124dc565b60405180910390fd5b610f9b8484848403610d4d565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611011576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110089061256e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611080576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107790612600565b60405180910390fd5b61108b83838361183e565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015611111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110890612692565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516111ff9190611c21565b60405180910390a361121284848461184e565b50505050565b611220610d45565b73ffffffffffffffffffffffffffffffffffffffff1661123e610954565b73ffffffffffffffffffffffffffffffffffffffff1614611294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128b906126fe565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fc9061276a565b60405180910390fd5b6113116000838361183e565b80600260008282546113239190611f44565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516113d49190611c21565b60405180910390a36113e86000838361184e565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361145b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611452906127fc565b60405180910390fd5b6114678260008361183e565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156114ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e49061288e565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008282540392505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516115a09190611c21565b60405180910390a36115b48360008461184e565b505050565b600080600084116115ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115f6906128fa565b60405180910390fd5b611607611853565b841115611649576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164090612966565b60405180910390fd5b6000611661858560000161186490919063ffffffff16565b90508360000180549050810361167e5760008092509250506116a7565b600184600101828154811061169657611695612986565b5b906000526020600020015492509250505b9250929050565b600090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000611785600861191d565b600061178f611853565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67816040516117c09190611c21565b60405180910390a18091505090565b600092915050565b611827600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611822836108d8565b611933565b50565b61183c6006611837610561565b611933565b565b611849838383610c7a565b505050565b505050565b600061185f6008610d37565b905090565b60008083805490500361187a5760009050611917565b600080848054905090505b808210156118ce57600061189983836119ae565b9050846118a687836119d4565b6000015411156118b8578091506118c8565b6001816118c59190611f44565b92505b50611885565b6000821180156118f65750836118f0866001856118eb91906121a8565b6119d4565b60000154145b156119115760018261190891906121a8565b92505050611917565b81925050505b92915050565b6001816000016000828254019250508190555050565b600061193d611853565b90508061194c846000016119f6565b10156119a95782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b600060028284186119bf91906129e4565b8284166119cc9190611f44565b905092915050565b600080836000528260206000200190506119ed81611a42565b91505092915050565b600080828054905003611a0c5760009050611a3d565b8160018380549050611a1e91906121a8565b81548110611a2f57611a2e612986565b5b906000526020600020015490505b919050565b6000819050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611a86578082015181840152602081019050611a6b565b60008484015250505050565b6000601f19601f8301169050919050565b6000611aae82611a4c565b611ab88185611a57565b9350611ac8818560208601611a68565b611ad181611a92565b840191505092915050565b60006020820190508181036000830152611af68184611aa3565b905092915050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611b3382611b08565b9050919050565b611b4381611b28565b8114611b4e57600080fd5b50565b600081359050611b6081611b3a565b92915050565b6000819050919050565b611b7981611b66565b8114611b8457600080fd5b50565b600081359050611b9681611b70565b92915050565b60008060408385031215611bb357611bb2611afe565b5b6000611bc185828601611b51565b9250506020611bd285828601611b87565b9150509250929050565b60008115159050919050565b611bf181611bdc565b82525050565b6000602082019050611c0c6000830184611be8565b92915050565b611c1b81611b66565b82525050565b6000602082019050611c366000830184611c12565b92915050565b600080600060608486031215611c5557611c54611afe565b5b6000611c6386828701611b51565b9350506020611c7486828701611b51565b9250506040611c8586828701611b87565b9150509250925092565b600060ff82169050919050565b611ca581611c8f565b82525050565b6000602082019050611cc06000830184611c9c565b92915050565b600060208284031215611cdc57611cdb611afe565b5b6000611cea84828501611b87565b91505092915050565b6000611cfe82611b28565b9050919050565b611d0e81611cf3565b8114611d1957600080fd5b50565b600081359050611d2b81611d05565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611d5657611d55611d31565b5b8235905067ffffffffffffffff811115611d7357611d72611d36565b5b602083019150836001820283011115611d8f57611d8e611d3b565b5b9250929050565b600080600080600060808688031215611db257611db1611afe565b5b6000611dc088828901611d1c565b9550506020611dd188828901611b51565b9450506040611de288828901611b87565b935050606086013567ffffffffffffffff811115611e0357611e02611b03565b5b611e0f88828901611d40565b92509250509295509295909350565b600060208284031215611e3457611e33611afe565b5b6000611e4284828501611b51565b91505092915050565b611e5481611b28565b82525050565b6000602082019050611e6f6000830184611e4b565b92915050565b60008060408385031215611e8c57611e8b611afe565b5b6000611e9a85828601611b51565b9250506020611eab85828601611b51565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611efc57607f821691505b602082108103611f0f57611f0e611eb5565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611f4f82611b66565b9150611f5a83611b66565b9250828201905080821115611f7257611f71611f15565b5b92915050565b7f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60008201527f6178466c6173684c6f616e000000000000000000000000000000000000000000602082015250565b6000611fd4602b83611a57565b9150611fdf82611f78565b604082019050919050565b6000602082019050818103600083015261200381611fc7565b9050919050565b600082825260208201905092915050565b82818337600083830152505050565b6000612036838561200a565b935061204383858461201b565b61204c83611a92565b840190509392505050565b600060a08201905061206c6000830189611e4b565b6120796020830188611e4b565b6120866040830187611c12565b6120936060830186611c12565b81810360808301526120a681848661202a565b9050979650505050505050565b6000819050919050565b6120c6816120b3565b81146120d157600080fd5b50565b6000815190506120e3816120bd565b92915050565b6000602082840312156120ff576120fe611afe565b5b600061210d848285016120d4565b91505092915050565b7f4552433230466c6173684d696e743a20696e76616c69642072657475726e207660008201527f616c756500000000000000000000000000000000000000000000000000000000602082015250565b6000612172602483611a57565b915061217d82612116565b604082019050919050565b600060208201905081810360008301526121a181612165565b9050919050565b60006121b382611b66565b91506121be83611b66565b92508282039050818111156121d6576121d5611f15565b5b92915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000612238602583611a57565b9150612243826121dc565b604082019050919050565b600060208201905081810360008301526122678161222b565b9050919050565b7f4552433230466c6173684d696e743a2077726f6e6720746f6b656e0000000000600082015250565b60006122a4601b83611a57565b91506122af8261226e565b602082019050919050565b600060208201905081810360008301526122d381612297565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000612336602683611a57565b9150612341826122da565b604082019050919050565b6000602082019050818103600083015261236581612329565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006123c8602483611a57565b91506123d38261236c565b604082019050919050565b600060208201905081810360008301526123f7816123bb565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b600061245a602283611a57565b9150612465826123fe565b604082019050919050565b600060208201905081810360008301526124898161244d565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b60006124c6601d83611a57565b91506124d182612490565b602082019050919050565b600060208201905081810360008301526124f5816124b9565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b6000612558602583611a57565b9150612563826124fc565b604082019050919050565b600060208201905081810360008301526125878161254b565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b60006125ea602383611a57565b91506125f58261258e565b604082019050919050565b60006020820190508181036000830152612619816125dd565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b600061267c602683611a57565b915061268782612620565b604082019050919050565b600060208201905081810360008301526126ab8161266f565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006126e8602083611a57565b91506126f3826126b2565b602082019050919050565b60006020820190508181036000830152612717816126db565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b6000612754601f83611a57565b915061275f8261271e565b602082019050919050565b6000602082019050818103600083015261278381612747565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b60006127e6602183611a57565b91506127f18261278a565b604082019050919050565b60006020820190508181036000830152612815816127d9565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b6000612878602283611a57565b91506128838261281c565b604082019050919050565b600060208201905081810360008301526128a78161286b565b9050919050565b7f4552433230536e617073686f743a206964206973203000000000000000000000600082015250565b60006128e4601683611a57565b91506128ef826128ae565b602082019050919050565b60006020820190508181036000830152612913816128d7565b9050919050565b7f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000600082015250565b6000612950601d83611a57565b915061295b8261291a565b602082019050919050565b6000602082019050818103600083015261297f81612943565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006129ef82611b66565b91506129fa83611b66565b925082612a0a57612a096129b5565b5b82820490509291505056fea264697066735822122004f7936d6e59cda0376212e6c871a286d6f3efd19a489c9b1031f07c8fbd474b64736f6c63430008120033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061014d5760003560e01c806370a08231116100c3578063981b24d01161007c578063981b24d0146103a0578063a457c2d7146103d0578063a9059cbb14610400578063d9d98ce414610430578063dd62ed3e14610460578063f2fde38b146104905761014d565b806370a0823114610304578063715018a61461033457806379cc67901461033e5780638da5cb5b1461035a57806395d89b41146103785780639711715a146103965761014d565b80633950935111610115578063395093511461020c57806340c10f191461023c57806342966c68146102585780634ee2cd7e146102745780635cffe9de146102a4578063613255ab146102d45761014d565b806306fdde0314610152578063095ea7b31461017057806318160ddd146101a057806323b872dd146101be578063313ce567146101ee575b600080fd5b61015a6104ac565b6040516101679190611adc565b60405180910390f35b61018a60048036038101906101859190611b9c565b61053e565b6040516101979190611bf7565b60405180910390f35b6101a8610561565b6040516101b59190611c21565b60405180910390f35b6101d860048036038101906101d39190611c3c565b61056b565b6040516101e59190611bf7565b60405180910390f35b6101f661059a565b6040516102039190611cab565b60405180910390f35b61022660048036038101906102219190611b9c565b6105a3565b6040516102339190611bf7565b60405180910390f35b61025660048036038101906102519190611b9c565b6105da565b005b610272600480360381019061026d9190611cc6565b6105f0565b005b61028e60048036038101906102899190611b9c565b610604565b60405161029b9190611c21565b60405180910390f35b6102be60048036038101906102b99190611d96565b610674565b6040516102cb9190611bf7565b60405180910390f35b6102ee60048036038101906102e99190611e1e565b610861565b6040516102fb9190611c21565b60405180910390f35b61031e60048036038101906103199190611e1e565b6108d8565b60405161032b9190611c21565b60405180910390f35b61033c610920565b005b61035860048036038101906103539190611b9c565b610934565b005b610362610954565b60405161036f9190611e5a565b60405180910390f35b61038061097e565b60405161038d9190611adc565b60405180910390f35b61039e610a10565b005b6103ba60048036038101906103b59190611cc6565b610a23565b6040516103c79190611c21565b60405180910390f35b6103ea60048036038101906103e59190611b9c565b610a54565b6040516103f79190611bf7565b60405180910390f35b61041a60048036038101906104159190611b9c565b610acb565b6040516104279190611bf7565b60405180910390f35b61044a60048036038101906104459190611b9c565b610aee565b6040516104579190611c21565b60405180910390f35b61047a60048036038101906104759190611e75565b610b70565b6040516104879190611c21565b60405180910390f35b6104aa60048036038101906104a59190611e1e565b610bf7565b005b6060600380546104bb90611ee4565b80601f01602080910402602001604051908101604052809291908181526020018280546104e790611ee4565b80156105345780601f1061050957610100808354040283529160200191610534565b820191906000526020600020905b81548152906001019060200180831161051757829003601f168201915b5050505050905090565b600080610549610d45565b9050610556818585610d4d565b600191505092915050565b6000600254905090565b600080610576610d45565b9050610583858285610f16565b61058e858585610fa2565b60019150509392505050565b60006012905090565b6000806105ae610d45565b90506105cf8185856105c08589610b70565b6105ca9190611f44565b610d4d565b600191505092915050565b6105e2611218565b6105ec8282611296565b5050565b6106016105fb610d45565b826113ec565b50565b600080600061065184600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206115b9565b915091508161066857610663856108d8565b61066a565b805b9250505092915050565b600061067f85610861565b8411156106c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b890611fea565b60405180910390fd5b60006106cd8686610aee565b90506106d98786611296565b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd98773ffffffffffffffffffffffffffffffffffffffff166323e30c8b338989868a8a6040518763ffffffff1660e01b815260040161073d96959493929190612057565b6020604051808303816000875af115801561075c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078091906120e9565b146107c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b790612188565b60405180910390fd5b60006107ca6116ae565b90506107e2883084896107dd9190611f44565b610f16565b600082148061081d5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b1561083c576108378883886108329190611f44565b6113ec565b610852565b61084688876113ec565b610851888284610fa2565b5b60019250505095945050505050565b60003073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461089d5760006108d1565b6108a5610561565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6108d091906121a8565b5b9050919050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610928611218565b61093260006116b3565b565b61094682610940610d45565b83610f16565b61095082826113ec565b5050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606004805461098d90611ee4565b80601f01602080910402602001604051908101604052809291908181526020018280546109b990611ee4565b8015610a065780601f106109db57610100808354040283529160200191610a06565b820191906000526020600020905b8154815290600101906020018083116109e957829003601f168201915b5050505050905090565b610a18611218565b610a20611779565b50565b6000806000610a338460066115b9565b9150915081610a4957610a44610561565b610a4b565b805b92505050919050565b600080610a5f610d45565b90506000610a6d8286610b70565b905083811015610ab2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa99061224e565b60405180910390fd5b610abf8286868403610d4d565b60019250505092915050565b600080610ad6610d45565b9050610ae3818585610fa2565b600191505092915050565b60003073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610b5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b55906122ba565b60405180910390fd5b610b6883836117cf565b905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610bff611218565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c659061234c565b60405180910390fd5b610c77816116b3565b50565b610c85838383610d32565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610ccf57610cc2826117d7565b610cca61182a565b610d2d565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d1957610d0c836117d7565b610d1461182a565b610d2c565b610d22836117d7565b610d2b826117d7565b5b5b505050565b505050565b600081600001549050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610dbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db3906123de565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2290612470565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051610f099190611c21565b60405180910390a3505050565b6000610f228484610b70565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610f9c5781811015610f8e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f85906124dc565b60405180910390fd5b610f9b8484848403610d4d565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611011576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110089061256e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611080576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107790612600565b60405180910390fd5b61108b83838361183e565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015611111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110890612692565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516111ff9190611c21565b60405180910390a361121284848461184e565b50505050565b611220610d45565b73ffffffffffffffffffffffffffffffffffffffff1661123e610954565b73ffffffffffffffffffffffffffffffffffffffff1614611294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128b906126fe565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fc9061276a565b60405180910390fd5b6113116000838361183e565b80600260008282546113239190611f44565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516113d49190611c21565b60405180910390a36113e86000838361184e565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361145b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611452906127fc565b60405180910390fd5b6114678260008361183e565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156114ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e49061288e565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008282540392505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516115a09190611c21565b60405180910390a36115b48360008461184e565b505050565b600080600084116115ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115f6906128fa565b60405180910390fd5b611607611853565b841115611649576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164090612966565b60405180910390fd5b6000611661858560000161186490919063ffffffff16565b90508360000180549050810361167e5760008092509250506116a7565b600184600101828154811061169657611695612986565b5b906000526020600020015492509250505b9250929050565b600090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000611785600861191d565b600061178f611853565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb67816040516117c09190611c21565b60405180910390a18091505090565b600092915050565b611827600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611822836108d8565b611933565b50565b61183c6006611837610561565b611933565b565b611849838383610c7a565b505050565b505050565b600061185f6008610d37565b905090565b60008083805490500361187a5760009050611917565b600080848054905090505b808210156118ce57600061189983836119ae565b9050846118a687836119d4565b6000015411156118b8578091506118c8565b6001816118c59190611f44565b92505b50611885565b6000821180156118f65750836118f0866001856118eb91906121a8565b6119d4565b60000154145b156119115760018261190891906121a8565b92505050611917565b81925050505b92915050565b6001816000016000828254019250508190555050565b600061193d611853565b90508061194c846000016119f6565b10156119a95782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b600060028284186119bf91906129e4565b8284166119cc9190611f44565b905092915050565b600080836000528260206000200190506119ed81611a42565b91505092915050565b600080828054905003611a0c5760009050611a3d565b8160018380549050611a1e91906121a8565b81548110611a2f57611a2e612986565b5b906000526020600020015490505b919050565b6000819050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611a86578082015181840152602081019050611a6b565b60008484015250505050565b6000601f19601f8301169050919050565b6000611aae82611a4c565b611ab88185611a57565b9350611ac8818560208601611a68565b611ad181611a92565b840191505092915050565b60006020820190508181036000830152611af68184611aa3565b905092915050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611b3382611b08565b9050919050565b611b4381611b28565b8114611b4e57600080fd5b50565b600081359050611b6081611b3a565b92915050565b6000819050919050565b611b7981611b66565b8114611b8457600080fd5b50565b600081359050611b9681611b70565b92915050565b60008060408385031215611bb357611bb2611afe565b5b6000611bc185828601611b51565b9250506020611bd285828601611b87565b9150509250929050565b60008115159050919050565b611bf181611bdc565b82525050565b6000602082019050611c0c6000830184611be8565b92915050565b611c1b81611b66565b82525050565b6000602082019050611c366000830184611c12565b92915050565b600080600060608486031215611c5557611c54611afe565b5b6000611c6386828701611b51565b9350506020611c7486828701611b51565b9250506040611c8586828701611b87565b9150509250925092565b600060ff82169050919050565b611ca581611c8f565b82525050565b6000602082019050611cc06000830184611c9c565b92915050565b600060208284031215611cdc57611cdb611afe565b5b6000611cea84828501611b87565b91505092915050565b6000611cfe82611b28565b9050919050565b611d0e81611cf3565b8114611d1957600080fd5b50565b600081359050611d2b81611d05565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611d5657611d55611d31565b5b8235905067ffffffffffffffff811115611d7357611d72611d36565b5b602083019150836001820283011115611d8f57611d8e611d3b565b5b9250929050565b600080600080600060808688031215611db257611db1611afe565b5b6000611dc088828901611d1c565b9550506020611dd188828901611b51565b9450506040611de288828901611b87565b935050606086013567ffffffffffffffff811115611e0357611e02611b03565b5b611e0f88828901611d40565b92509250509295509295909350565b600060208284031215611e3457611e33611afe565b5b6000611e4284828501611b51565b91505092915050565b611e5481611b28565b82525050565b6000602082019050611e6f6000830184611e4b565b92915050565b60008060408385031215611e8c57611e8b611afe565b5b6000611e9a85828601611b51565b9250506020611eab85828601611b51565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611efc57607f821691505b602082108103611f0f57611f0e611eb5565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611f4f82611b66565b9150611f5a83611b66565b9250828201905080821115611f7257611f71611f15565b5b92915050565b7f4552433230466c6173684d696e743a20616d6f756e742065786365656473206d60008201527f6178466c6173684c6f616e000000000000000000000000000000000000000000602082015250565b6000611fd4602b83611a57565b9150611fdf82611f78565b604082019050919050565b6000602082019050818103600083015261200381611fc7565b9050919050565b600082825260208201905092915050565b82818337600083830152505050565b6000612036838561200a565b935061204383858461201b565b61204c83611a92565b840190509392505050565b600060a08201905061206c6000830189611e4b565b6120796020830188611e4b565b6120866040830187611c12565b6120936060830186611c12565b81810360808301526120a681848661202a565b9050979650505050505050565b6000819050919050565b6120c6816120b3565b81146120d157600080fd5b50565b6000815190506120e3816120bd565b92915050565b6000602082840312156120ff576120fe611afe565b5b600061210d848285016120d4565b91505092915050565b7f4552433230466c6173684d696e743a20696e76616c69642072657475726e207660008201527f616c756500000000000000000000000000000000000000000000000000000000602082015250565b6000612172602483611a57565b915061217d82612116565b604082019050919050565b600060208201905081810360008301526121a181612165565b9050919050565b60006121b382611b66565b91506121be83611b66565b92508282039050818111156121d6576121d5611f15565b5b92915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000612238602583611a57565b9150612243826121dc565b604082019050919050565b600060208201905081810360008301526122678161222b565b9050919050565b7f4552433230466c6173684d696e743a2077726f6e6720746f6b656e0000000000600082015250565b60006122a4601b83611a57565b91506122af8261226e565b602082019050919050565b600060208201905081810360008301526122d381612297565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000612336602683611a57565b9150612341826122da565b604082019050919050565b6000602082019050818103600083015261236581612329565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006123c8602483611a57565b91506123d38261236c565b604082019050919050565b600060208201905081810360008301526123f7816123bb565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b600061245a602283611a57565b9150612465826123fe565b604082019050919050565b600060208201905081810360008301526124898161244d565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b60006124c6601d83611a57565b91506124d182612490565b602082019050919050565b600060208201905081810360008301526124f5816124b9565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b6000612558602583611a57565b9150612563826124fc565b604082019050919050565b600060208201905081810360008301526125878161254b565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b60006125ea602383611a57565b91506125f58261258e565b604082019050919050565b60006020820190508181036000830152612619816125dd565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b600061267c602683611a57565b915061268782612620565b604082019050919050565b600060208201905081810360008301526126ab8161266f565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006126e8602083611a57565b91506126f3826126b2565b602082019050919050565b60006020820190508181036000830152612717816126db565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b6000612754601f83611a57565b915061275f8261271e565b602082019050919050565b6000602082019050818103600083015261278381612747565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b60006127e6602183611a57565b91506127f18261278a565b604082019050919050565b60006020820190508181036000830152612815816127d9565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b6000612878602283611a57565b91506128838261281c565b604082019050919050565b600060208201905081810360008301526128a78161286b565b9050919050565b7f4552433230536e617073686f743a206964206973203000000000000000000000600082015250565b60006128e4601683611a57565b91506128ef826128ae565b602082019050919050565b60006020820190508181036000830152612913816128d7565b9050919050565b7f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000600082015250565b6000612950601d83611a57565b915061295b8261291a565b602082019050919050565b6000602082019050818103600083015261297f81612943565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006129ef82611b66565b91506129fa83611b66565b925082612a0a57612a096129b5565b5b82820490509291505056fea264697066735822122004f7936d6e59cda0376212e6c871a286d6f3efd19a489c9b1031f07c8fbd474b64736f6c63430008120033

Deployed Bytecode Sourcemap

58585:652:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32354:100;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34705:201;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33474:108;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35486:295;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33316:93;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36190:238;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;58863:95;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;57899:91;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;53415:266;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;47390:959;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;44476:178;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33645:127;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;25761:103;;;:::i;:::-;;58309:164;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;25113:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32573:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;58788:67;;;:::i;:::-;;53785:234;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36931:436;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33978:193;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;45030:219;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34234:151;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;26019:201;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;32354:100;32408:13;32441:5;32434:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32354:100;:::o;34705:201::-;34788:4;34805:13;34821:12;:10;:12::i;:::-;34805:28;;34844:32;34853:5;34860:7;34869:6;34844:8;:32::i;:::-;34894:4;34887:11;;;34705:201;;;;:::o;33474:108::-;33535:7;33562:12;;33555:19;;33474:108;:::o;35486:295::-;35617:4;35634:15;35652:12;:10;:12::i;:::-;35634:30;;35675:38;35691:4;35697:7;35706:6;35675:15;:38::i;:::-;35724:27;35734:4;35740:2;35744:6;35724:9;:27::i;:::-;35769:4;35762:11;;;35486:295;;;;;:::o;33316:93::-;33374:5;33399:2;33392:9;;33316:93;:::o;36190:238::-;36278:4;36295:13;36311:12;:10;:12::i;:::-;36295:28;;36334:64;36343:5;36350:7;36387:10;36359:25;36369:5;36376:7;36359:9;:25::i;:::-;:38;;;;:::i;:::-;36334:8;:64::i;:::-;36416:4;36409:11;;;36190:238;;;;:::o;58863:95::-;24999:13;:11;:13::i;:::-;58933:17:::1;58939:2;58943:6;58933:5;:17::i;:::-;58863:95:::0;;:::o;57899:91::-;57955:27;57961:12;:10;:12::i;:::-;57975:6;57955:5;:27::i;:::-;57899:91;:::o;53415:266::-;53502:7;53523:16;53541:13;53558:55;53567:10;53579:24;:33;53604:7;53579:33;;;;;;;;;;;;;;;53558:8;:55::i;:::-;53522:91;;;;53633:11;:40;;53655:18;53665:7;53655:9;:18::i;:::-;53633:40;;;53647:5;53633:40;53626:47;;;;53415:266;;;;:::o;47390:959::-;47569:4;47604:19;47617:5;47604:12;:19::i;:::-;47594:6;:29;;47586:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;47682:11;47696:23;47705:5;47712:6;47696:8;:23::i;:::-;47682:37;;47730:32;47744:8;47755:6;47730:5;:32::i;:::-;44213:45;47795:8;:20;;;47816:10;47828:5;47835:6;47843:3;47848:4;;47795:58;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:75;47773:161;;;;;;;;;;;;:::i;:::-;;;;;;;;;47945:24;47972:19;:17;:19::i;:::-;47945:46;;48002:63;48026:8;48045:4;48061:3;48052:6;:12;;;;:::i;:::-;48002:15;:63::i;:::-;48087:1;48080:3;:8;:42;;;;48120:1;48092:30;;:16;:30;;;48080:42;48076:244;;;48139:38;48153:8;48173:3;48164:6;:12;;;;:::i;:::-;48139:5;:38::i;:::-;48076:244;;;48210:32;48224:8;48235:6;48210:5;:32::i;:::-;48257:51;48275:8;48286:16;48304:3;48257:9;:51::i;:::-;48076:244;48337:4;48330:11;;;;47390:959;;;;;;;:::o;44476:178::-;44551:7;44595:4;44578:22;;:5;:22;;;:68;;44645:1;44578:68;;;44623:19;:17;:19::i;:::-;44603:17;:39;;;;:::i;:::-;44578:68;44571:75;;44476:178;;;:::o;33645:127::-;33719:7;33746:9;:18;33756:7;33746:18;;;;;;;;;;;;;;;;33739:25;;33645:127;;;:::o;25761:103::-;24999:13;:11;:13::i;:::-;25826:30:::1;25853:1;25826:18;:30::i;:::-;25761:103::o:0;58309:164::-;58386:46;58402:7;58411:12;:10;:12::i;:::-;58425:6;58386:15;:46::i;:::-;58443:22;58449:7;58458:6;58443:5;:22::i;:::-;58309:164;;:::o;25113:87::-;25159:7;25186:6;;;;;;;;;;;25179:13;;25113:87;:::o;32573:104::-;32629:13;32662:7;32655:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32573:104;:::o;58788:67::-;24999:13;:11;:13::i;:::-;58836:11:::1;:9;:11::i;:::-;;58788:67::o:0;53785:234::-;53857:7;53878:16;53896:13;53913:43;53922:10;53934:21;53913:8;:43::i;:::-;53877:79;;;;53976:11;:35;;53998:13;:11;:13::i;:::-;53976:35;;;53990:5;53976:35;53969:42;;;;53785:234;;;:::o;36931:436::-;37024:4;37041:13;37057:12;:10;:12::i;:::-;37041:28;;37080:24;37107:25;37117:5;37124:7;37107:9;:25::i;:::-;37080:52;;37171:15;37151:16;:35;;37143:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;37264:60;37273:5;37280:7;37308:15;37289:16;:34;37264:8;:60::i;:::-;37355:4;37348:11;;;;36931:436;;;;:::o;33978:193::-;34057:4;34074:13;34090:12;:10;:12::i;:::-;34074:28;;34113;34123:5;34130:2;34134:6;34113:9;:28::i;:::-;34159:4;34152:11;;;33978:193;;;;:::o;45030:219::-;45117:7;45162:4;45145:22;;:5;:22;;;45137:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;45217:24;45227:5;45234:6;45217:9;:24::i;:::-;45210:31;;45030:219;;;;:::o;34234:151::-;34323:7;34350:11;:18;34362:5;34350:18;;;;;;;;;;;;;;;:27;34369:7;34350:27;;;;;;;;;;;;;;;;34343:34;;34234:151;;;;:::o;26019:201::-;24999:13;:11;:13::i;:::-;26128:1:::1;26108:22;;:8;:22;;::::0;26100:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;26184:28;26203:8;26184:18;:28::i;:::-;26019:201:::0;:::o;54236:622::-;54379:44;54406:4;54412:2;54416:6;54379:26;:44::i;:::-;54456:1;54440:18;;:4;:18;;;54436:415;;54496:26;54519:2;54496:22;:26::i;:::-;54537:28;:26;:28::i;:::-;54436:415;;;54601:1;54587:16;;:2;:16;;;54583:268;;54641:28;54664:4;54641:22;:28::i;:::-;54684;:26;:28::i;:::-;54583:268;;;54770:28;54793:4;54770:22;:28::i;:::-;54813:26;54836:2;54813:22;:26::i;:::-;54583:268;54436:415;54236:622;;;:::o;42682:125::-;;;;:::o;3375:114::-;3440:7;3467;:14;;;3460:21;;3375:114;;;:::o;23658:98::-;23711:7;23738:10;23731:17;;23658:98;:::o;40958:380::-;41111:1;41094:19;;:5;:19;;;41086:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;41192:1;41173:21;;:7;:21;;;41165:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;41276:6;41246:11;:18;41258:5;41246:18;;;;;;;;;;;;;;;:27;41265:7;41246:27;;;;;;;;;;;;;;;:36;;;;41314:7;41298:32;;41307:5;41298:32;;;41323:6;41298:32;;;;;;:::i;:::-;;;;;;;;40958:380;;;:::o;41629:453::-;41764:24;41791:25;41801:5;41808:7;41791:9;:25::i;:::-;41764:52;;41851:17;41831:16;:37;41827:248;;41913:6;41893:16;:26;;41885:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;41997:51;42006:5;42013:7;42041:6;42022:16;:25;41997:8;:51::i;:::-;41827:248;41753:329;41629:453;;;:::o;37837:840::-;37984:1;37968:18;;:4;:18;;;37960:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;38061:1;38047:16;;:2;:16;;;38039:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;38116:38;38137:4;38143:2;38147:6;38116:20;:38::i;:::-;38167:19;38189:9;:15;38199:4;38189:15;;;;;;;;;;;;;;;;38167:37;;38238:6;38223:11;:21;;38215:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;38355:6;38341:11;:20;38323:9;:15;38333:4;38323:15;;;;;;;;;;;;;;;:38;;;;38558:6;38541:9;:13;38551:2;38541:13;;;;;;;;;;;;;;;;:23;;;;;;;;;;;38608:2;38593:26;;38602:4;38593:26;;;38612:6;38593:26;;;;;;:::i;:::-;;;;;;;;38632:37;38652:4;38658:2;38662:6;38632:19;:37::i;:::-;37949:728;37837:840;;;:::o;25278:132::-;25353:12;:10;:12::i;:::-;25342:23;;:7;:5;:7::i;:::-;:23;;;25334:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;25278:132::o;38964:548::-;39067:1;39048:21;;:7;:21;;;39040:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;39118:49;39147:1;39151:7;39160:6;39118:20;:49::i;:::-;39196:6;39180:12;;:22;;;;;;;:::i;:::-;;;;;;;;39373:6;39351:9;:18;39361:7;39351:18;;;;;;;;;;;;;;;;:28;;;;;;;;;;;39427:7;39406:37;;39423:1;39406:37;;;39436:6;39406:37;;;;;;:::i;:::-;;;;;;;;39456:48;39484:1;39488:7;39497:6;39456:19;:48::i;:::-;38964:548;;:::o;39845:675::-;39948:1;39929:21;;:7;:21;;;39921:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;40001:49;40022:7;40039:1;40043:6;40001:20;:49::i;:::-;40063:22;40088:9;:18;40098:7;40088:18;;;;;;;;;;;;;;;;40063:43;;40143:6;40125:14;:24;;40117:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;40262:6;40245:14;:23;40224:9;:18;40234:7;40224:18;;;;;;;;;;;;;;;:44;;;;40379:6;40363:12;;:22;;;;;;;;;;;40440:1;40414:37;;40423:7;40414:37;;;40444:6;40414:37;;;;;;:::i;:::-;;;;;;;;40464:48;40484:7;40501:1;40505:6;40464:19;:48::i;:::-;39910:610;39845:675;;:::o;54866:1619::-;54955:4;54961:7;55002:1;54989:10;:14;54981:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;55063:23;:21;:23::i;:::-;55049:10;:37;;55041:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;56259:13;56275:40;56304:10;56275:9;:13;;:28;;:40;;;;:::i;:::-;56259:56;;56341:9;:13;;:20;;;;56332:5;:29;56328:150;;56386:5;56393:1;56378:17;;;;;;;56328:150;56436:4;56442:9;:16;;56459:5;56442:23;;;;;;;;:::i;:::-;;;;;;;;;;56428:38;;;;;54866:1619;;;;;;:::o;46209:105::-;46269:7;46209:105;:::o;26380:191::-;26454:16;26473:6;;;;;;;;;;;26454:25;;26499:8;26490:6;;:17;;;;;;;;;;;;;;;;;;26554:8;26523:40;;26544:8;26523:40;;;;;;;;;;;;26443:128;26380:191;:::o;52887:223::-;52934:7;52954:30;:18;:28;:30::i;:::-;52997:17;53017:23;:21;:23::i;:::-;52997:43;;53056:19;53065:9;53056:19;;;;;;:::i;:::-;;;;;;;;53093:9;53086:16;;;52887:223;:::o;45648:234::-;45729:7;45648:234;;;;:::o;56493:146::-;56561:70;56577:24;:33;56602:7;56577:33;;;;;;;;;;;;;;;56612:18;56622:7;56612:9;:18::i;:::-;56561:15;:70::i;:::-;56493:146;:::o;56647:118::-;56704:53;56720:21;56743:13;:11;:13::i;:::-;56704:15;:53::i;:::-;56647:118::o;59036:198::-;59182:44;59209:4;59215:2;59219:6;59182:26;:44::i;:::-;59036:198;;;:::o;43411:124::-;;;;:::o;53176:127::-;53240:7;53267:28;:18;:26;:28::i;:::-;53260:35;;53176:127;:::o;20355:958::-;20444:7;20484:1;20468:5;:12;;;;:17;20464:58;;20509:1;20502:8;;;;20464:58;20534:11;20560:12;20575:5;:12;;;;20560:27;;20600:444;20613:4;20607:3;:10;20600:444;;;20634:11;20648:23;20661:3;20666:4;20648:12;:23::i;:::-;20634:37;;20925:7;20892:24;20905:5;20912:3;20892:12;:24::i;:::-;:30;;;:40;20888:145;;;20960:3;20953:10;;20888:145;;;21016:1;21010:3;:7;;;;:::i;:::-;21004:13;;20888:145;20619:425;20600:444;;;21170:1;21164:3;:7;:56;;;;;21213:7;21175:28;21188:5;21201:1;21195:3;:7;;;;:::i;:::-;21175:12;:28::i;:::-;:34;;;:45;21164:56;21160:146;;;21250:1;21244:3;:7;;;;:::i;:::-;21237:14;;;;;;21160:146;21291:3;21284:10;;;;20355:958;;;;;:::o;3497:127::-;3604:1;3586:7;:14;;;:19;;;;;;;;;;;3497:127;:::o;56773:310::-;56868:17;56888:23;:21;:23::i;:::-;56868:43;;56959:9;56926:30;56942:9;:13;;56926:15;:30::i;:::-;:42;56922:154;;;56985:9;:13;;57004:9;56985:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57029:9;:16;;57051:12;57029:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56922:154;56857:226;56773:310;;:::o;4837:156::-;4899:7;4984:1;4979;4975;:5;4974:11;;;;:::i;:::-;4969:1;4965;:5;4964:21;;;;:::i;:::-;4957:28;;4837:156;;;;:::o;22624:342::-;22705:31;22749:12;22850:8;22847:1;22840:19;22905:3;22898:4;22895:1;22885:18;22881:28;22873:36;;22937:21;:4;:19;:21::i;:::-;22930:28;;;22624:342;;;;:::o;57091:212::-;57161:7;57199:1;57185:3;:10;;;;:15;57181:115;;57224:1;57217:8;;;;57181:115;57265:3;57282:1;57269:3;:10;;;;:14;;;;:::i;:::-;57265:19;;;;;;;;:::i;:::-;;;;;;;;;;57258:26;;57091:212;;;;:::o;19443:195::-;19504:21;19616:4;19606:14;;19443:195;;;:::o;7:99:1:-;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:169::-;196:11;230:6;225:3;218:19;270:4;265:3;261:14;246:29;;112:169;;;;:::o;287:246::-;368:1;378:113;392:6;389:1;386:13;378:113;;;477:1;472:3;468:11;462:18;458:1;453:3;449:11;442:39;414:2;411:1;407:10;402:15;;378:113;;;525:1;516:6;511:3;507:16;500:27;349:184;287:246;;;:::o;539:102::-;580:6;631:2;627:7;622:2;615:5;611:14;607:28;597:38;;539:102;;;:::o;647:377::-;735:3;763:39;796:5;763:39;:::i;:::-;818:71;882:6;877:3;818:71;:::i;:::-;811:78;;898:65;956:6;951:3;944:4;937:5;933:16;898:65;:::i;:::-;988:29;1010:6;988:29;:::i;:::-;983:3;979:39;972:46;;739:285;647:377;;;;:::o;1030:313::-;1143:4;1181:2;1170:9;1166:18;1158:26;;1230:9;1224:4;1220:20;1216:1;1205:9;1201:17;1194:47;1258:78;1331:4;1322:6;1258:78;:::i;:::-;1250:86;;1030:313;;;;:::o;1430:117::-;1539:1;1536;1529:12;1553:117;1662:1;1659;1652:12;1676:126;1713:7;1753:42;1746:5;1742:54;1731:65;;1676:126;;;:::o;1808:96::-;1845:7;1874:24;1892:5;1874:24;:::i;:::-;1863:35;;1808:96;;;:::o;1910:122::-;1983:24;2001:5;1983:24;:::i;:::-;1976:5;1973:35;1963:63;;2022:1;2019;2012:12;1963:63;1910:122;:::o;2038:139::-;2084:5;2122:6;2109:20;2100:29;;2138:33;2165:5;2138:33;:::i;:::-;2038:139;;;;:::o;2183:77::-;2220:7;2249:5;2238:16;;2183:77;;;:::o;2266:122::-;2339:24;2357:5;2339:24;:::i;:::-;2332:5;2329:35;2319:63;;2378:1;2375;2368:12;2319:63;2266:122;:::o;2394:139::-;2440:5;2478:6;2465:20;2456:29;;2494:33;2521:5;2494:33;:::i;:::-;2394:139;;;;:::o;2539:474::-;2607:6;2615;2664:2;2652:9;2643:7;2639:23;2635:32;2632:119;;;2670:79;;:::i;:::-;2632:119;2790:1;2815:53;2860:7;2851:6;2840:9;2836:22;2815:53;:::i;:::-;2805:63;;2761:117;2917:2;2943:53;2988:7;2979:6;2968:9;2964:22;2943:53;:::i;:::-;2933:63;;2888:118;2539:474;;;;;:::o;3019:90::-;3053:7;3096:5;3089:13;3082:21;3071:32;;3019:90;;;:::o;3115:109::-;3196:21;3211:5;3196:21;:::i;:::-;3191:3;3184:34;3115:109;;:::o;3230:210::-;3317:4;3355:2;3344:9;3340:18;3332:26;;3368:65;3430:1;3419:9;3415:17;3406:6;3368:65;:::i;:::-;3230:210;;;;:::o;3446:118::-;3533:24;3551:5;3533:24;:::i;:::-;3528:3;3521:37;3446:118;;:::o;3570:222::-;3663:4;3701:2;3690:9;3686:18;3678:26;;3714:71;3782:1;3771:9;3767:17;3758:6;3714:71;:::i;:::-;3570:222;;;;:::o;3798:619::-;3875:6;3883;3891;3940:2;3928:9;3919:7;3915:23;3911:32;3908:119;;;3946:79;;:::i;:::-;3908:119;4066:1;4091:53;4136:7;4127:6;4116:9;4112:22;4091:53;:::i;:::-;4081:63;;4037:117;4193:2;4219:53;4264:7;4255:6;4244:9;4240:22;4219:53;:::i;:::-;4209:63;;4164:118;4321:2;4347:53;4392:7;4383:6;4372:9;4368:22;4347:53;:::i;:::-;4337:63;;4292:118;3798:619;;;;;:::o;4423:86::-;4458:7;4498:4;4491:5;4487:16;4476:27;;4423:86;;;:::o;4515:112::-;4598:22;4614:5;4598:22;:::i;:::-;4593:3;4586:35;4515:112;;:::o;4633:214::-;4722:4;4760:2;4749:9;4745:18;4737:26;;4773:67;4837:1;4826:9;4822:17;4813:6;4773:67;:::i;:::-;4633:214;;;;:::o;4853:329::-;4912:6;4961:2;4949:9;4940:7;4936:23;4932:32;4929:119;;;4967:79;;:::i;:::-;4929:119;5087:1;5112:53;5157:7;5148:6;5137:9;5133:22;5112:53;:::i;:::-;5102:63;;5058:117;4853:329;;;;:::o;5188:124::-;5253:7;5282:24;5300:5;5282:24;:::i;:::-;5271:35;;5188:124;;;:::o;5318:178::-;5419:52;5465:5;5419:52;:::i;:::-;5412:5;5409:63;5399:91;;5486:1;5483;5476:12;5399:91;5318:178;:::o;5502:195::-;5576:5;5614:6;5601:20;5592:29;;5630:61;5685:5;5630:61;:::i;:::-;5502:195;;;;:::o;5703:117::-;5812:1;5809;5802:12;5826:117;5935:1;5932;5925:12;5949:117;6058:1;6055;6048:12;6085:552;6142:8;6152:6;6202:3;6195:4;6187:6;6183:17;6179:27;6169:122;;6210:79;;:::i;:::-;6169:122;6323:6;6310:20;6300:30;;6353:18;6345:6;6342:30;6339:117;;;6375:79;;:::i;:::-;6339:117;6489:4;6481:6;6477:17;6465:29;;6543:3;6535:4;6527:6;6523:17;6513:8;6509:32;6506:41;6503:128;;;6550:79;;:::i;:::-;6503:128;6085:552;;;;;:::o;6643:1019::-;6768:6;6776;6784;6792;6800;6849:3;6837:9;6828:7;6824:23;6820:33;6817:120;;;6856:79;;:::i;:::-;6817:120;6976:1;7001:81;7074:7;7065:6;7054:9;7050:22;7001:81;:::i;:::-;6991:91;;6947:145;7131:2;7157:53;7202:7;7193:6;7182:9;7178:22;7157:53;:::i;:::-;7147:63;;7102:118;7259:2;7285:53;7330:7;7321:6;7310:9;7306:22;7285:53;:::i;:::-;7275:63;;7230:118;7415:2;7404:9;7400:18;7387:32;7446:18;7438:6;7435:30;7432:117;;;7468:79;;:::i;:::-;7432:117;7581:64;7637:7;7628:6;7617:9;7613:22;7581:64;:::i;:::-;7563:82;;;;7358:297;6643:1019;;;;;;;;:::o;7668:329::-;7727:6;7776:2;7764:9;7755:7;7751:23;7747:32;7744:119;;;7782:79;;:::i;:::-;7744:119;7902:1;7927:53;7972:7;7963:6;7952:9;7948:22;7927:53;:::i;:::-;7917:63;;7873:117;7668:329;;;;:::o;8003:118::-;8090:24;8108:5;8090:24;:::i;:::-;8085:3;8078:37;8003:118;;:::o;8127:222::-;8220:4;8258:2;8247:9;8243:18;8235:26;;8271:71;8339:1;8328:9;8324:17;8315:6;8271:71;:::i;:::-;8127:222;;;;:::o;8355:474::-;8423:6;8431;8480:2;8468:9;8459:7;8455:23;8451:32;8448:119;;;8486:79;;:::i;:::-;8448:119;8606:1;8631:53;8676:7;8667:6;8656:9;8652:22;8631:53;:::i;:::-;8621:63;;8577:117;8733:2;8759:53;8804:7;8795:6;8784:9;8780:22;8759:53;:::i;:::-;8749:63;;8704:118;8355:474;;;;;:::o;8835:180::-;8883:77;8880:1;8873:88;8980:4;8977:1;8970:15;9004:4;9001:1;8994:15;9021:320;9065:6;9102:1;9096:4;9092:12;9082:22;;9149:1;9143:4;9139:12;9170:18;9160:81;;9226:4;9218:6;9214:17;9204:27;;9160:81;9288:2;9280:6;9277:14;9257:18;9254:38;9251:84;;9307:18;;:::i;:::-;9251:84;9072:269;9021:320;;;:::o;9347:180::-;9395:77;9392:1;9385:88;9492:4;9489:1;9482:15;9516:4;9513:1;9506:15;9533:191;9573:3;9592:20;9610:1;9592:20;:::i;:::-;9587:25;;9626:20;9644:1;9626:20;:::i;:::-;9621:25;;9669:1;9666;9662:9;9655:16;;9690:3;9687:1;9684:10;9681:36;;;9697:18;;:::i;:::-;9681:36;9533:191;;;;:::o;9730:230::-;9870:34;9866:1;9858:6;9854:14;9847:58;9939:13;9934:2;9926:6;9922:15;9915:38;9730:230;:::o;9966:366::-;10108:3;10129:67;10193:2;10188:3;10129:67;:::i;:::-;10122:74;;10205:93;10294:3;10205:93;:::i;:::-;10323:2;10318:3;10314:12;10307:19;;9966:366;;;:::o;10338:419::-;10504:4;10542:2;10531:9;10527:18;10519:26;;10591:9;10585:4;10581:20;10577:1;10566:9;10562:17;10555:47;10619:131;10745:4;10619:131;:::i;:::-;10611:139;;10338:419;;;:::o;10763:168::-;10846:11;10880:6;10875:3;10868:19;10920:4;10915:3;10911:14;10896:29;;10763:168;;;;:::o;10937:146::-;11034:6;11029:3;11024;11011:30;11075:1;11066:6;11061:3;11057:16;11050:27;10937:146;;;:::o;11111:314::-;11207:3;11228:70;11291:6;11286:3;11228:70;:::i;:::-;11221:77;;11308:56;11357:6;11352:3;11345:5;11308:56;:::i;:::-;11389:29;11411:6;11389:29;:::i;:::-;11384:3;11380:39;11373:46;;11111:314;;;;;:::o;11431:771::-;11664:4;11702:3;11691:9;11687:19;11679:27;;11716:71;11784:1;11773:9;11769:17;11760:6;11716:71;:::i;:::-;11797:72;11865:2;11854:9;11850:18;11841:6;11797:72;:::i;:::-;11879;11947:2;11936:9;11932:18;11923:6;11879:72;:::i;:::-;11961;12029:2;12018:9;12014:18;12005:6;11961:72;:::i;:::-;12081:9;12075:4;12071:20;12065:3;12054:9;12050:19;12043:49;12109:86;12190:4;12181:6;12173;12109:86;:::i;:::-;12101:94;;11431:771;;;;;;;;;:::o;12208:77::-;12245:7;12274:5;12263:16;;12208:77;;;:::o;12291:122::-;12364:24;12382:5;12364:24;:::i;:::-;12357:5;12354:35;12344:63;;12403:1;12400;12393:12;12344:63;12291:122;:::o;12419:143::-;12476:5;12507:6;12501:13;12492:22;;12523:33;12550:5;12523:33;:::i;:::-;12419:143;;;;:::o;12568:351::-;12638:6;12687:2;12675:9;12666:7;12662:23;12658:32;12655:119;;;12693:79;;:::i;:::-;12655:119;12813:1;12838:64;12894:7;12885:6;12874:9;12870:22;12838:64;:::i;:::-;12828:74;;12784:128;12568:351;;;;:::o;12925:223::-;13065:34;13061:1;13053:6;13049:14;13042:58;13134:6;13129:2;13121:6;13117:15;13110:31;12925:223;:::o;13154:366::-;13296:3;13317:67;13381:2;13376:3;13317:67;:::i;:::-;13310:74;;13393:93;13482:3;13393:93;:::i;:::-;13511:2;13506:3;13502:12;13495:19;;13154:366;;;:::o;13526:419::-;13692:4;13730:2;13719:9;13715:18;13707:26;;13779:9;13773:4;13769:20;13765:1;13754:9;13750:17;13743:47;13807:131;13933:4;13807:131;:::i;:::-;13799:139;;13526:419;;;:::o;13951:194::-;13991:4;14011:20;14029:1;14011:20;:::i;:::-;14006:25;;14045:20;14063:1;14045:20;:::i;:::-;14040:25;;14089:1;14086;14082:9;14074:17;;14113:1;14107:4;14104:11;14101:37;;;14118:18;;:::i;:::-;14101:37;13951:194;;;;:::o;14151:224::-;14291:34;14287:1;14279:6;14275:14;14268:58;14360:7;14355:2;14347:6;14343:15;14336:32;14151:224;:::o;14381:366::-;14523:3;14544:67;14608:2;14603:3;14544:67;:::i;:::-;14537:74;;14620:93;14709:3;14620:93;:::i;:::-;14738:2;14733:3;14729:12;14722:19;;14381:366;;;:::o;14753:419::-;14919:4;14957:2;14946:9;14942:18;14934:26;;15006:9;15000:4;14996:20;14992:1;14981:9;14977:17;14970:47;15034:131;15160:4;15034:131;:::i;:::-;15026:139;;14753:419;;;:::o;15178:177::-;15318:29;15314:1;15306:6;15302:14;15295:53;15178:177;:::o;15361:366::-;15503:3;15524:67;15588:2;15583:3;15524:67;:::i;:::-;15517:74;;15600:93;15689:3;15600:93;:::i;:::-;15718:2;15713:3;15709:12;15702:19;;15361:366;;;:::o;15733:419::-;15899:4;15937:2;15926:9;15922:18;15914:26;;15986:9;15980:4;15976:20;15972:1;15961:9;15957:17;15950:47;16014:131;16140:4;16014:131;:::i;:::-;16006:139;;15733:419;;;:::o;16158:225::-;16298:34;16294:1;16286:6;16282:14;16275:58;16367:8;16362:2;16354:6;16350:15;16343:33;16158:225;:::o;16389:366::-;16531:3;16552:67;16616:2;16611:3;16552:67;:::i;:::-;16545:74;;16628:93;16717:3;16628:93;:::i;:::-;16746:2;16741:3;16737:12;16730:19;;16389:366;;;:::o;16761:419::-;16927:4;16965:2;16954:9;16950:18;16942:26;;17014:9;17008:4;17004:20;17000:1;16989:9;16985:17;16978:47;17042:131;17168:4;17042:131;:::i;:::-;17034:139;;16761:419;;;:::o;17186:223::-;17326:34;17322:1;17314:6;17310:14;17303:58;17395:6;17390:2;17382:6;17378:15;17371:31;17186:223;:::o;17415:366::-;17557:3;17578:67;17642:2;17637:3;17578:67;:::i;:::-;17571:74;;17654:93;17743:3;17654:93;:::i;:::-;17772:2;17767:3;17763:12;17756:19;;17415:366;;;:::o;17787:419::-;17953:4;17991:2;17980:9;17976:18;17968:26;;18040:9;18034:4;18030:20;18026:1;18015:9;18011:17;18004:47;18068:131;18194:4;18068:131;:::i;:::-;18060:139;;17787:419;;;:::o;18212:221::-;18352:34;18348:1;18340:6;18336:14;18329:58;18421:4;18416:2;18408:6;18404:15;18397:29;18212:221;:::o;18439:366::-;18581:3;18602:67;18666:2;18661:3;18602:67;:::i;:::-;18595:74;;18678:93;18767:3;18678:93;:::i;:::-;18796:2;18791:3;18787:12;18780:19;;18439:366;;;:::o;18811:419::-;18977:4;19015:2;19004:9;19000:18;18992:26;;19064:9;19058:4;19054:20;19050:1;19039:9;19035:17;19028:47;19092:131;19218:4;19092:131;:::i;:::-;19084:139;;18811:419;;;:::o;19236:179::-;19376:31;19372:1;19364:6;19360:14;19353:55;19236:179;:::o;19421:366::-;19563:3;19584:67;19648:2;19643:3;19584:67;:::i;:::-;19577:74;;19660:93;19749:3;19660:93;:::i;:::-;19778:2;19773:3;19769:12;19762:19;;19421:366;;;:::o;19793:419::-;19959:4;19997:2;19986:9;19982:18;19974:26;;20046:9;20040:4;20036:20;20032:1;20021:9;20017:17;20010:47;20074:131;20200:4;20074:131;:::i;:::-;20066:139;;19793:419;;;:::o;20218:224::-;20358:34;20354:1;20346:6;20342:14;20335:58;20427:7;20422:2;20414:6;20410:15;20403:32;20218:224;:::o;20448:366::-;20590:3;20611:67;20675:2;20670:3;20611:67;:::i;:::-;20604:74;;20687:93;20776:3;20687:93;:::i;:::-;20805:2;20800:3;20796:12;20789:19;;20448:366;;;:::o;20820:419::-;20986:4;21024:2;21013:9;21009:18;21001:26;;21073:9;21067:4;21063:20;21059:1;21048:9;21044:17;21037:47;21101:131;21227:4;21101:131;:::i;:::-;21093:139;;20820:419;;;:::o;21245:222::-;21385:34;21381:1;21373:6;21369:14;21362:58;21454:5;21449:2;21441:6;21437:15;21430:30;21245:222;:::o;21473:366::-;21615:3;21636:67;21700:2;21695:3;21636:67;:::i;:::-;21629:74;;21712:93;21801:3;21712:93;:::i;:::-;21830:2;21825:3;21821:12;21814:19;;21473:366;;;:::o;21845:419::-;22011:4;22049:2;22038:9;22034:18;22026:26;;22098:9;22092:4;22088:20;22084:1;22073:9;22069:17;22062:47;22126:131;22252:4;22126:131;:::i;:::-;22118:139;;21845:419;;;:::o;22270:225::-;22410:34;22406:1;22398:6;22394:14;22387:58;22479:8;22474:2;22466:6;22462:15;22455:33;22270:225;:::o;22501:366::-;22643:3;22664:67;22728:2;22723:3;22664:67;:::i;:::-;22657:74;;22740:93;22829:3;22740:93;:::i;:::-;22858:2;22853:3;22849:12;22842:19;;22501:366;;;:::o;22873:419::-;23039:4;23077:2;23066:9;23062:18;23054:26;;23126:9;23120:4;23116:20;23112:1;23101:9;23097:17;23090:47;23154:131;23280:4;23154:131;:::i;:::-;23146:139;;22873:419;;;:::o;23298:182::-;23438:34;23434:1;23426:6;23422:14;23415:58;23298:182;:::o;23486:366::-;23628:3;23649:67;23713:2;23708:3;23649:67;:::i;:::-;23642:74;;23725:93;23814:3;23725:93;:::i;:::-;23843:2;23838:3;23834:12;23827:19;;23486:366;;;:::o;23858:419::-;24024:4;24062:2;24051:9;24047:18;24039:26;;24111:9;24105:4;24101:20;24097:1;24086:9;24082:17;24075:47;24139:131;24265:4;24139:131;:::i;:::-;24131:139;;23858:419;;;:::o;24283:181::-;24423:33;24419:1;24411:6;24407:14;24400:57;24283:181;:::o;24470:366::-;24612:3;24633:67;24697:2;24692:3;24633:67;:::i;:::-;24626:74;;24709:93;24798:3;24709:93;:::i;:::-;24827:2;24822:3;24818:12;24811:19;;24470:366;;;:::o;24842:419::-;25008:4;25046:2;25035:9;25031:18;25023:26;;25095:9;25089:4;25085:20;25081:1;25070:9;25066:17;25059:47;25123:131;25249:4;25123:131;:::i;:::-;25115:139;;24842:419;;;:::o;25267:220::-;25407:34;25403:1;25395:6;25391:14;25384:58;25476:3;25471:2;25463:6;25459:15;25452:28;25267:220;:::o;25493:366::-;25635:3;25656:67;25720:2;25715:3;25656:67;:::i;:::-;25649:74;;25732:93;25821:3;25732:93;:::i;:::-;25850:2;25845:3;25841:12;25834:19;;25493:366;;;:::o;25865:419::-;26031:4;26069:2;26058:9;26054:18;26046:26;;26118:9;26112:4;26108:20;26104:1;26093:9;26089:17;26082:47;26146:131;26272:4;26146:131;:::i;:::-;26138:139;;25865:419;;;:::o;26290:221::-;26430:34;26426:1;26418:6;26414:14;26407:58;26499:4;26494:2;26486:6;26482:15;26475:29;26290:221;:::o;26517:366::-;26659:3;26680:67;26744:2;26739:3;26680:67;:::i;:::-;26673:74;;26756:93;26845:3;26756:93;:::i;:::-;26874:2;26869:3;26865:12;26858:19;;26517:366;;;:::o;26889:419::-;27055:4;27093:2;27082:9;27078:18;27070:26;;27142:9;27136:4;27132:20;27128:1;27117:9;27113:17;27106:47;27170:131;27296:4;27170:131;:::i;:::-;27162:139;;26889:419;;;:::o;27314:172::-;27454:24;27450:1;27442:6;27438:14;27431:48;27314:172;:::o;27492:366::-;27634:3;27655:67;27719:2;27714:3;27655:67;:::i;:::-;27648:74;;27731:93;27820:3;27731:93;:::i;:::-;27849:2;27844:3;27840:12;27833:19;;27492:366;;;:::o;27864:419::-;28030:4;28068:2;28057:9;28053:18;28045:26;;28117:9;28111:4;28107:20;28103:1;28092:9;28088:17;28081:47;28145:131;28271:4;28145:131;:::i;:::-;28137:139;;27864:419;;;:::o;28289:179::-;28429:31;28425:1;28417:6;28413:14;28406:55;28289:179;:::o;28474:366::-;28616:3;28637:67;28701:2;28696:3;28637:67;:::i;:::-;28630:74;;28713:93;28802:3;28713:93;:::i;:::-;28831:2;28826:3;28822:12;28815:19;;28474:366;;;:::o;28846:419::-;29012:4;29050:2;29039:9;29035:18;29027:26;;29099:9;29093:4;29089:20;29085:1;29074:9;29070:17;29063:47;29127:131;29253:4;29127:131;:::i;:::-;29119:139;;28846:419;;;:::o;29271:180::-;29319:77;29316:1;29309:88;29416:4;29413:1;29406:15;29440:4;29437:1;29430:15;29457:180;29505:77;29502:1;29495:88;29602:4;29599:1;29592:15;29626:4;29623:1;29616:15;29643:185;29683:1;29700:20;29718:1;29700:20;:::i;:::-;29695:25;;29734:20;29752:1;29734:20;:::i;:::-;29729:25;;29773:1;29763:35;;29778:18;;:::i;:::-;29763:35;29820:1;29817;29813:9;29808:14;;29643:185;;;;:::o

Swarm Source

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