ETH Price: $3,176.35 (-7.90%)

Contract

0x88266f9eb705F5282a2507A9c418821a2AC9f8BD

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

TokenTracker

Nutcash (NCASH) (@$0.0126)
Transaction Hash
Method
Block
From
To
Approve2345412572024-07-21 13:38:593 days ago1721569139IN
Nutcash: NCASH Token
0 ETH0.000000630.01
Approve2310467752024-07-11 10:01:4714 days ago1720692107IN
Nutcash: NCASH Token
0 ETH0.00000120.01
Approve2241273022024-06-21 8:34:4734 days ago1718958887IN
Nutcash: NCASH Token
0 ETH0.000002260.047779
Approve2229112042024-06-17 20:02:1037 days ago1718654530IN
Nutcash: NCASH Token
0 ETH0.000001090.01
Approve2229105372024-06-17 19:59:2237 days ago1718654362IN
Nutcash: NCASH Token
0 ETH0.000001090.01
Transfer2228802822024-06-17 17:52:5137 days ago1718646771IN
Nutcash: NCASH Token
0 ETH0.000001260.01
Approve2163136272024-05-29 17:03:2256 days ago1717002202IN
Nutcash: NCASH Token
0 ETH0.000001450.01
Approve2155237782024-05-27 9:38:3659 days ago1716802716IN
Nutcash: NCASH Token
0 ETH0.000000950.01
Approve2152950092024-05-26 17:29:4359 days ago1716744583IN
Nutcash: NCASH Token
0 ETH0.00000070.01
Approve2148478922024-05-25 9:58:4361 days ago1716631123IN
Nutcash: NCASH Token
0 ETH0.000000590.01
Approve2145132412024-05-24 10:20:1762 days ago1716546017IN
Nutcash: NCASH Token
0 ETH0.00000080.01
Approve2138972142024-05-22 14:32:5563 days ago1716388375IN
Nutcash: NCASH Token
0 ETH0.000001410.014109
Approve2132292792024-05-20 15:02:1365 days ago1716217333IN
Nutcash: NCASH Token
0 ETH0.000001030.01
Approve2132031032024-05-20 13:11:4865 days ago1716210708IN
Nutcash: NCASH Token
0 ETH0.000000710.01
Approve2122510802024-05-17 17:10:4868 days ago1715965848IN
Nutcash: NCASH Token
0 ETH0.000000890.012842
Approve2122499332024-05-17 17:05:3968 days ago1715965539IN
Nutcash: NCASH Token
0 ETH0.000000980.014674
Approve2122443732024-05-17 16:39:3968 days ago1715963979IN
Nutcash: NCASH Token
0 ETH0.000000620.01
Approve2121982562024-05-17 13:13:4068 days ago1715951620IN
Nutcash: NCASH Token
0 ETH0.000001120.018315
Transfer2121967492024-05-17 13:07:1768 days ago1715951237IN
Nutcash: NCASH Token
0 ETH0.00000150.02261
Transfer2094249592024-05-09 9:46:5577 days ago1715248015IN
Nutcash: NCASH Token
0 ETH0.000000610.01
Approve2093080042024-05-09 1:37:1077 days ago1715218630IN
Nutcash: NCASH Token
0 ETH0.000000630.01
Approve2090907942024-05-08 10:24:0578 days ago1715163845IN
Nutcash: NCASH Token
0 ETH0.000000570.01
Approve2081789572024-05-05 18:42:2880 days ago1714934548IN
Nutcash: NCASH Token
0 ETH0.000000650.01
Approve2077820872024-05-04 15:00:4581 days ago1714834845IN
Nutcash: NCASH Token
0 ETH0.000000680.01
Approve2073469902024-05-03 8:36:4583 days ago1714725405IN
Nutcash: NCASH Token
0 ETH0.000000620.01
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Nutcash

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Arbiscan.io on 2024-03-28
*/

// SPDX-License-Identifier: MIT
// File: @openzeppelin/[email protected]/utils/Nonces.sol

// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)
pragma solidity ^0.8.20;

/**
 * @dev Provides tracking nonces for addresses. Nonces will only increment.
 */
abstract contract Nonces {
    /**
     * @dev The nonce used for an `account` is not the expected current nonce.
     */
    error InvalidAccountNonce(address account, uint256 currentNonce);

    mapping(address account => uint256) private _nonces;

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

    /**
     * @dev Consumes a nonce.
     *
     * Returns the current value and increments nonce.
     */
    function _useNonce(address owner) internal virtual returns (uint256) {
        // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be
        // decremented or reset. This guarantees that the nonce never overflows.
        unchecked {
            // It is important to do x++ and not ++x here.
            return _nonces[owner]++;
        }
    }

    /**
     * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.
     */
    function _useCheckedNonce(address owner, uint256 nonce) internal virtual {
        uint256 current = _useNonce(owner);
        if (nonce != current) {
            revert InvalidAccountNonce(owner, current);
        }
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)

pragma solidity ^0.8.20;

interface IERC5267 {
    /**
     * @dev MAY be emitted to signal that the domain could have changed.
     */
    event EIP712DomainChanged();

    /**
     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
     * signature.
     */
    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

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

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

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

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

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

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

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

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(
        string storage store
    ) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

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

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(
        bytes storage store
    ) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol)

pragma solidity ^0.8.20;

// | string  | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA   |
// | length  | 0x                                                              BB |
type ShortString is bytes32;

/**
 * @dev This library provides functions to convert short memory strings
 * into a `ShortString` type that can be used as an immutable variable.
 *
 * Strings of arbitrary length can be optimized using this library if
 * they are short enough (up to 31 bytes) by packing them with their
 * length (1 byte) in a single EVM word (32 bytes). Additionally, a
 * fallback mechanism can be used for every other case.
 *
 * Usage example:
 *
 * ```solidity
 * contract Named {
 *     using ShortStrings for *;
 *
 *     ShortString private immutable _name;
 *     string private _nameFallback;
 *
 *     constructor(string memory contractName) {
 *         _name = contractName.toShortStringWithFallback(_nameFallback);
 *     }
 *
 *     function name() external view returns (string memory) {
 *         return _name.toStringWithFallback(_nameFallback);
 *     }
 * }
 * ```
 */
library ShortStrings {
    // Used as an identifier for strings longer than 31 bytes.
    bytes32 private constant FALLBACK_SENTINEL =
        0x00000000000000000000000000000000000000000000000000000000000000FF;

    error StringTooLong(string str);
    error InvalidShortString();

    /**
     * @dev Encode a string of at most 31 chars into a `ShortString`.
     *
     * This will trigger a `StringTooLong` error is the input string is too long.
     */
    function toShortString(
        string memory str
    ) internal pure returns (ShortString) {
        bytes memory bstr = bytes(str);
        if (bstr.length > 31) {
            revert StringTooLong(str);
        }
        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
    }

    /**
     * @dev Decode a `ShortString` back to a "normal" string.
     */
    function toString(ShortString sstr) internal pure returns (string memory) {
        uint256 len = byteLength(sstr);
        // using `new string(len)` would work locally but is not memory safe.
        string memory str = new string(32);
        /// @solidity memory-safe-assembly
        assembly {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

    /**
     * @dev Return the length of a `ShortString`.
     */
    function byteLength(ShortString sstr) internal pure returns (uint256) {
        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
        if (result > 31) {
            revert InvalidShortString();
        }
        return result;
    }

    /**
     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
     */
    function toShortStringWithFallback(
        string memory value,
        string storage store
    ) internal returns (ShortString) {
        if (bytes(value).length < 32) {
            return toShortString(value);
        } else {
            StorageSlot.getStringSlot(store).value = value;
            return ShortString.wrap(FALLBACK_SENTINEL);
        }
    }

    /**
     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     */
    function toStringWithFallback(
        ShortString value,
        string storage store
    ) internal pure returns (string memory) {
        if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
            return toString(value);
        } else {
            return store;
        }
    }

    /**
     * @dev Return the length of a string that was encoded to `ShortString` or written to storage using
     * {setWithFallback}.
     *
     * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
     * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
     */
    function byteLengthWithFallback(
        ShortString value,
        string storage store
    ) internal view returns (uint256) {
        if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
            return byteLength(value);
        } else {
            return bytes(store).length;
        }
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

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

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(
        uint256 a,
        uint256 b
    ) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(
        uint256 a,
        uint256 b
    ) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(
        uint256 a,
        uint256 b
    ) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(
        uint256 a,
        uint256 b
    ) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(
        uint256 a,
        uint256 b
    ) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @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 towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (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 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 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.

            uint256 twos = denominator & (0 - denominator);
            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 (unsignedRoundsUp(rounding) && 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
     * towards zero.
     *
     * 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 +
                (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * 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 +
                (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * 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 +
                (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

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

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

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(
        int256 value
    ) internal pure returns (string memory) {
        return
            string.concat(
                value < 0 ? "-" : "",
                toString(SignedMath.abs(value))
            );
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

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

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
     * representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(
        string memory a,
        string memory b
    ) internal pure returns (bool) {
        return
            bytes(a).length == bytes(b).length &&
            keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)

pragma solidity ^0.8.20;

/**
 * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
 *
 * The library provides methods for generating a hash of a message that conforms to the
 * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
 * specifications.
 */
library MessageHashUtils {
    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x45` (`personal_sign` messages).
     *
     * The digest is calculated by prefixing a bytes32 `messageHash` with
     * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
     *
     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
     * keccak256, although any bytes32 value can be safely used because the final digest will
     * be re-hashed.
     *
     * See {ECDSA-recover}.
     */
    function toEthSignedMessageHash(
        bytes32 messageHash
    ) internal pure returns (bytes32 digest) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
        }
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x45` (`personal_sign` messages).
     *
     * The digest is calculated by prefixing an arbitrary `message` with
     * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
     *
     * See {ECDSA-recover}.
     */
    function toEthSignedMessageHash(
        bytes memory message
    ) internal pure returns (bytes32) {
        return
            keccak256(
                bytes.concat(
                    "\x19Ethereum Signed Message:\n",
                    bytes(Strings.toString(message.length)),
                    message
                )
            );
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x00` (data with intended validator).
     *
     * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
     * `validator` address. Then hashing the result.
     *
     * See {ECDSA-recover}.
     */
    function toDataWithIntendedValidatorHash(
        address validator,
        bytes memory data
    ) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(hex"19_00", validator, data));
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).
     *
     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
     * `\x19\x01` and hashing the result. It corresponds to the hash signed by the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
     *
     * See {ECDSA-recover}.
     */
    function toTypedDataHash(
        bytes32 domainSeparator,
        bytes32 structHash
    ) internal pure returns (bytes32 digest) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, hex"19_01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            digest := keccak256(ptr, 0x42)
        }
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.20;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
 * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract
 * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to
 * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
 * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the
 * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
 *
 * @custom:oz-upgrades-unsafe-allow state-variable-immutable
 */
abstract contract EIP712 is IERC5267 {
    using ShortStrings for *;

    bytes32 private constant TYPE_HASH =
        keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );

    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    ShortString private immutable _name;
    ShortString private immutable _version;
    string private _nameFallback;
    string private _versionFallback;

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        _name = name.toShortStringWithFallback(_nameFallback);
        _version = version.toShortStringWithFallback(_versionFallback);
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
            return _cachedDomainSeparator;
        } else {
            return _buildDomainSeparator();
        }
    }

    function _buildDomainSeparator() private view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    TYPE_HASH,
                    _hashedName,
                    _hashedVersion,
                    block.chainid,
                    address(this)
                )
            );
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(
        bytes32 structHash
    ) internal view virtual returns (bytes32) {
        return
            MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @dev See {IERC-5267}.
     */
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f", // 01111
            _EIP712Name(),
            _EIP712Version(),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }

    /**
     * @dev The name parameter for the EIP712 domain.
     *
     * NOTE: By default this function reads _name which is an immutable value.
     * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
     */
    // solhint-disable-next-line func-name-mixedcase
    function _EIP712Name() internal view returns (string memory) {
        return _name.toStringWithFallback(_nameFallback);
    }

    /**
     * @dev The version parameter for the EIP712 domain.
     *
     * NOTE: By default this function reads _version which is an immutable value.
     * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
     */
    // solhint-disable-next-line func-name-mixedcase
    function _EIP712Version() internal view returns (string memory) {
        return _version.toStringWithFallback(_versionFallback);
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS
    }

    /**
     * @dev The signature derives the `address(0)`.
     */
    error ECDSAInvalidSignature();

    /**
     * @dev The signature has an invalid length.
     */
    error ECDSAInvalidSignatureLength(uint256 length);

    /**
     * @dev The signature has an S value that is in the upper half order.
     */
    error ECDSAInvalidSignatureS(bytes32 s);

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
     * return address(0) without also returning an error description. Errors are documented using an enum (error type)
     * and a bytes32 providing additional information about the error.
     *
     * If no error is returned, then the address can be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     */
    function tryRecover(
        bytes32 hash,
        bytes memory signature
    ) internal pure returns (address, RecoverError, bytes32) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (
                address(0),
                RecoverError.InvalidSignatureLength,
                bytes32(signature.length)
            );
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     */
    function recover(
        bytes32 hash,
        bytes memory signature
    ) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(
            hash,
            signature
        );
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError, bytes32) {
        unchecked {
            bytes32 s = vs &
                bytes32(
                    0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                );
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            uint8 v = uint8((uint256(vs) >> 255) + 27);
            return tryRecover(hash, v, r, s);
        }
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(
            hash,
            r,
            vs
        );
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError, bytes32) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (
            uint256(s) >
            0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
        ) {
            return (address(0), RecoverError.InvalidSignatureS, s);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature, bytes32(0));
        }

        return (signer, RecoverError.NoError, bytes32(0));
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(
            hash,
            v,
            r,
            s
        );
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
     */
    function _throwError(RecoverError error, bytes32 errorArg) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert ECDSAInvalidSignature();
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert ECDSAInvalidSignatureLength(uint256(errorArg));
        } else if (error == RecoverError.InvalidSignatureS) {
            revert ECDSAInvalidSignatureS(errorArg);
        }
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

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

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

// File: @openzeppelin/[email protected]/interfaces/draft-IERC6093.sol

// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(
        address sender,
        uint256 balance,
        uint256 needed
    );

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(
        address spender,
        uint256 allowance,
        uint256 needed
    );

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(
        address sender,
        uint256 balance,
        uint256 needed,
        uint256 tokenId
    );

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

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

// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value
    ) external returns (bool);
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
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 v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

/**
 * @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}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

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

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

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual 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 `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(
        address spender,
        uint256 value
    ) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        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 `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` 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.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` 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.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(
        address owner,
        address spender,
        uint256 value,
        bool emitEvent
    ) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

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

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

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {
    bytes32 private constant PERMIT_TYPEHASH =
        keccak256(
            "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
        );

    /**
     * @dev Permit deadline has expired.
     */
    error ERC2612ExpiredSignature(uint256 deadline);

    /**
     * @dev Mismatched signature.
     */
    error ERC2612InvalidSigner(address signer, address owner);

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

    /**
     * @inheritdoc IERC20Permit
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        if (block.timestamp > deadline) {
            revert ERC2612ExpiredSignature(deadline);
        }

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

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        if (signer != owner) {
            revert ERC2612InvalidSigner(signer, owner);
        }

        _approve(owner, spender, value);
    }

    /**
     * @inheritdoc IERC20Permit
     */
    function nonces(
        address owner
    ) public view virtual override(IERC20Permit, Nonces) returns (uint256) {
        return super.nonces(owner);
    }

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

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

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.20;

/**
 * @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 a `value` amount of tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 value) public virtual {
        _burn(_msgSender(), value);
    }

    /**
     * @dev Destroys a `value` amount of 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
     * `value`.
     */
    function burnFrom(address account, uint256 value) public virtual {
        _spendAllowance(account, _msgSender(), value);
        _burn(account, value);
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

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

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(
            data
        );
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(
        address target,
        bytes memory data
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(
        address target,
        bytes memory data
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata
    ) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(
        address spender,
        uint256 currentAllowance,
        uint256 requestedDecrease
    );

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(
            token,
            abi.encodeCall(token.transferFrom, (from, to, value))
        );
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 requestedDecrease
    ) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(
                    spender,
                    currentAllowance,
                    requestedDecrease
                );
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        bytes memory approvalCall = abi.encodeCall(
            token.approve,
            (spender, value)
        );

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(
                token,
                abi.encodeCall(token.approve, (spender, 0))
            );
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(
        IERC20 token,
        bytes memory data
    ) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success &&
            (returndata.length == 0 || abi.decode(returndata, (bool))) &&
            address(token).code.length > 0;
    }
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

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

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(
        uint256 tokenId
    ) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(
        address owner,
        address operator
    ) external view returns (bool);
}

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

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be
     * reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/[email protected]/token/ERC721/utils/ERC721Holder.sol

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)

pragma solidity ^0.8.20;

/**
 * @dev Implementation of the {IERC721Receiver} interface.
 *
 * Accepts all token transfers.
 * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
 * {IERC721-setApprovalForAll}.
 */
abstract contract ERC721Holder is IERC721Receiver {
    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     *
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public virtual returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

// File: Nutcash.sol

// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;

/// @title Nutcash (NCASH) Token & Staking Contract with NCASH rewards
/// @notice Staking Implementation distributes Nutcash ERC20 token rewards,
/// proportionally based on the amount of tokens staked by each staker at any given time.
/// @dev Every 1 NUTS or 1 NUTS404 or 10B NUT or 1M WEN or 1k NCASH staked gives: ~1 NCASH / week.
/// There is a halving every ~4years during 16 years (meaning that rewards will be divide by 2 every 4 year during the first 16 years of Nutcash deployment).
/// When/if NCASH supply reaches 21M max supply, staking rewards are paused and resume when/if supply decreases due to NCASH burning.
contract Nutcash is ERC20, ERC20Burnable, ERC20Permit, ERC721Holder {
    using SafeERC20 for IERC20;

    /* ========== STATE VARIABLES ========== */

    uint256 public constant MAX_SUPPLY = 21000000000000000000000000; // = 21M NCASH

    // halving every 4 years from 1st one: 01/04/2028 4:20pm GMT to last one: 01/04/2040 4:20pm GMT
    uint256 public constant HALVING_TIMESTAMP_1 = 1838218800;
    uint256 public constant HALVING_TIMESTAMP_2 = 1964449200;
    uint256 public constant HALVING_TIMESTAMP_3 = 2090679600;
    uint256 public constant HALVING_TIMESTAMP_4 = 2216910000;

    // NB: REWARDS_PER_SECOND_0 = ~1 / (7*24*60*60) * coeff * 10**-18 NCASH / second (with no NCASH unit)
    uint256 public constant REWARDS_PER_SECOND_0 = 160;
    uint256 public constant REWARDS_PER_SECOND_1 = 80;
    uint256 public constant REWARDS_PER_SECOND_2 = 40;
    uint256 public constant REWARDS_PER_SECOND_3 = 20;
    uint256 public constant REWARDS_PER_SECOND_4 = 10;

    /// @dev Struct that holds staker info for each user (handles both ERC721 & ERC20 staked token).
    struct Staker {
        uint256 staked; // The ERC20 tokens staked by the user.
        uint256[] stakedTokenIds; // The array of ERC721 Token Ids staked by the user.
        uint256 timeOfLastUpdate; // The time of the last update of the rewards.
        uint256 unclaimedRewards; // The amount of NCASH ERC20 Reward Tokens that have not been claimed by the user.
    }

    enum Symbol {
        NUTS,
        NUTS404,
        NUT,
        WEN,
        NCASH
    }

    mapping(Symbol => mapping(address => Staker)) public stakers; // Mapping of Token (ERC20 or ER721) stakers to their staking info.
    mapping(Symbol => uint256) public totalStakedSupply; // for front end info purpose only
    mapping(Symbol => uint256) public rewardCoeffs;
    mapping(Symbol => address) public token;
    mapping(Symbol => uint256) public minStake;

    mapping(uint256 => address) public stakerAddressNUTS; // Mapping of Token Id to staker address for NUTS NFT.
    address[] public stakersArrayNUTS; // Array of stakers addresses for NUTS NFT.
    mapping(address => uint256) public stakerToArrayIndexNUTS; // Mapping of stakers addresses to their index in the stakersArray for NUTS NFT.
    mapping(uint256 => uint256) public tokenIdToArrayIndexNUTS; // Mapping of Token Id to it's index in the staker's stakedTokenIds array for NUTS NFT.

    /* ========== EVENTS ========== */

    event Staked(address indexed user, Symbol symbol, uint256[] tokenIds);
    event Staked(address indexed user, Symbol symbol, uint256 amount);
    event Withdrawn(address indexed user, Symbol symbol, uint256[] tokenIds);
    event Withdrawn(address indexed user, Symbol symbol, uint256 amount);
    event RewardPaid(address indexed user, Symbol symbol, uint256 reward);

    /* ========== CONSTRUCTOR ========== */

    constructor() ERC20("Nutcash", "NCASH") ERC20Permit("Nutcash") {
        _mint(msg.sender, 10500000 * 10 ** decimals());

        rewardCoeffs[Symbol.NUTS] = 1e10;
        rewardCoeffs[Symbol.NUTS404] = 1e10;
        rewardCoeffs[Symbol.NUT] = 1;
        rewardCoeffs[Symbol.WEN] = 1e4;
        rewardCoeffs[Symbol.NCASH] = 1e7;

        token[Symbol.NUTS] = 0xa844Cb1b558625c8A6214D460f2FcFA599eB464a;
        token[Symbol.NUTS404] = 0x37b2f564971d3BF986Dc9e46ec587f42b75BDe76;
        token[Symbol.NUT] = 0x8697841B82C71fcbd9E58C15F6dE68CD1C63Fd02;
        token[Symbol.WEN] = 0x860Ea9299e9C297FBde64143cab2A3cB01945a27;
        token[Symbol.NCASH] = address(this);

        minStake[Symbol.NUTS] = 1; // 1 NUTS min
        minStake[Symbol.NUTS404] = 1e15; // 0.001 NUTS404 min
        minStake[Symbol.NUT] = 1e18; // 1 NUT min
        minStake[Symbol.WEN] = 1e15; // 0.001 WEN min
        minStake[Symbol.NCASH] = 1e14; // 0.0001 NCASH min
    }

    /**
     * @notice Function used to calculate the rewards for a user.
     * @return _rewards - The rewards for the user.
     */
    function calculateRewards(
        Symbol _symbol,
        address _staker
    ) internal view returns (uint256 _rewards) {
        Staker memory staker = stakers[_symbol][_staker];

        // Update rewardsPerSecond according to current time & halving timestamps
        uint256 rewardsPerSecond;
        if (block.timestamp < HALVING_TIMESTAMP_1) {
            rewardsPerSecond = REWARDS_PER_SECOND_0;
        } else if (block.timestamp < HALVING_TIMESTAMP_2) {
            rewardsPerSecond = REWARDS_PER_SECOND_1;
        } else if (block.timestamp < HALVING_TIMESTAMP_3) {
            rewardsPerSecond = REWARDS_PER_SECOND_2;
        } else if (block.timestamp < HALVING_TIMESTAMP_4) {
            rewardsPerSecond = REWARDS_PER_SECOND_3;
        } else {
            rewardsPerSecond = REWARDS_PER_SECOND_4;
        }

        uint256 tokenNumber = _symbol != Symbol.NUTS
            ? staker.staked
            : staker.stakedTokenIds.length;

        // NB: all input staked ERC20 have the same unit (18 decimals)
        uint256 unit = _symbol != Symbol.NUTS ? 1e18 : 1;

        return (((block.timestamp - staker.timeOfLastUpdate) *
            tokenNumber *
            rewardsPerSecond *
            rewardCoeffs[_symbol]) / unit);
    }

    /**
     * @notice Function used to update the unclaimed rewards for the sender.
     * @param _symbol - The symbol of the token staked.
     */
    function _updateUnclaimedRewards(Symbol _symbol) internal {
        Staker storage staker = stakers[_symbol][msg.sender];

        staker.unclaimedRewards += calculateRewards(_symbol, msg.sender);
        staker.timeOfLastUpdate = block.timestamp;
    }

    /**
     * @notice Function used to reset the unclaimed rewards for the sender when claimRewards is called.
     * @param _symbol - The symbol of the token staked.
     */
    function _resetUnclaimedRewards(Symbol _symbol) internal {
        Staker storage staker = stakers[_symbol][msg.sender];

        staker.unclaimedRewards = 0;
        staker.timeOfLastUpdate = block.timestamp;
    }

    /**
     * @notice Function used to stake ERC721 Nuts (NUTS) Tokens.
     * @param _tokenIds - The array of NUTS Token Ids to stake.
     * @dev Each Token Id must be approved for transfer by the user before calling this function.
     */
    function stakeNUTS(uint256[] calldata _tokenIds) external {
        require(
            _tokenIds.length >= minStake[Symbol.NUTS],
            "Token number must be higher than minimimum deposit"
        );

        Staker storage staker = stakers[Symbol.NUTS][msg.sender];

        if (staker.stakedTokenIds.length > 0) {
            _updateUnclaimedRewards(Symbol.NUTS);
        } else {
            stakersArrayNUTS.push(msg.sender);
            stakerToArrayIndexNUTS[msg.sender] = stakersArrayNUTS.length - 1;
            staker.timeOfLastUpdate = block.timestamp;
        }

        uint256 amount = _tokenIds.length;
        for (uint256 i; i < amount; ) {
            IERC721(token[Symbol.NUTS]).safeTransferFrom(
                msg.sender,
                address(this),
                _tokenIds[i]
            );

            staker.stakedTokenIds.push(_tokenIds[i]);
            tokenIdToArrayIndexNUTS[_tokenIds[i]] =
                staker.stakedTokenIds.length -
                1;
            stakerAddressNUTS[_tokenIds[i]] = msg.sender;
            unchecked {
                i++;
            }
        }
        totalStakedSupply[Symbol.NUTS] += amount;

        emit Staked(msg.sender, Symbol.NUTS, _tokenIds);
    }

    /**
     * @notice Function used to withdraw ERC721 Nuts (NUTS) Tokens.
     * @param _tokenIds - The array of NUTS Token Ids to withdraw.
     */
    function withdrawNUTS(uint256[] memory _tokenIds) public {
        require(_tokenIds.length != 0, "No tokenIds provided");

        Staker storage staker = stakers[Symbol.NUTS][msg.sender];
        require(
            staker.stakedTokenIds.length > 0,
            "No tokens staked to withdraw"
        );
        _updateUnclaimedRewards(Symbol.NUTS);

        uint256 amount = _tokenIds.length;
        for (uint256 i; i < amount; ) {
            require(
                stakerAddressNUTS[_tokenIds[i]] == msg.sender,
                "Not the staker of the token"
            );

            uint256 index = tokenIdToArrayIndexNUTS[_tokenIds[i]];
            uint256 lastTokenIndex = staker.stakedTokenIds.length - 1;
            if (index != lastTokenIndex) {
                staker.stakedTokenIds[index] = staker.stakedTokenIds[
                    lastTokenIndex
                ];
                tokenIdToArrayIndexNUTS[staker.stakedTokenIds[index]] = index;
            }
            staker.stakedTokenIds.pop();

            delete stakerAddressNUTS[_tokenIds[i]];

            IERC721(token[Symbol.NUTS]).safeTransferFrom(
                address(this),
                msg.sender,
                _tokenIds[i]
            );

            unchecked {
                i++;
            }
        }
        totalStakedSupply[Symbol.NUTS] -= amount;

        if (staker.stakedTokenIds.length == 0) {
            uint256 index = stakerToArrayIndexNUTS[msg.sender];
            uint256 lastStakerIndex = stakersArrayNUTS.length - 1;
            if (index != lastStakerIndex) {
                stakersArrayNUTS[index] = stakersArrayNUTS[lastStakerIndex];
                stakerToArrayIndexNUTS[stakersArrayNUTS[index]] = index;
            }
            stakersArrayNUTS.pop();
        }
        emit Withdrawn(msg.sender, Symbol.NUTS, _tokenIds);
    }

    /**
     * @notice Function used to claim the accrued ERC20 Nutcash (NCASH) Reward Tokens for msg.sender
     */
    function _claimRewards(Symbol _symbol) internal {
        uint256 rewards = calculateRewards(_symbol, msg.sender) +
            stakers[_symbol][msg.sender].unclaimedRewards;
        require(rewards > 0, "No rewards to claim");
        require(totalSupply() + rewards <= MAX_SUPPLY, "Exceeds MAX_SUPPLY"); // Never mint token(s) exceeding MAX_SUPPLY

        _resetUnclaimedRewards(_symbol);

        _mint(msg.sender, rewards);

        emit RewardPaid(msg.sender, _symbol, rewards);
    }

    function claimRewardsNUTS() public {
        _claimRewards(Symbol.NUTS);
    }

    /**
     * @notice Function used to get the info for a user: the Nuts (NUTS) Token Ids staked and the available Nutcash (NCASH) rewards.
     * @param _user - The address of the user.
     * @return _stakedTokenIds - The array of Token Ids staked by the user.
     * @return _availableRewards - The available rewards for the user.
     * @dev This includes both the rewards stored but not claimed and the rewards accumulated since the last update.
     */
    function userStakeInfoNUTS(
        address _user
    )
        external
        view
        returns (uint256[] memory _stakedTokenIds, uint256 _availableRewards)
    {
        Staker memory _staker = stakers[Symbol.NUTS][_user];
        _availableRewards = _staker.stakedTokenIds.length == 0
            ? _staker.unclaimedRewards
            : _staker.unclaimedRewards + calculateRewards(Symbol.NUTS, _user);

        return (_staker.stakedTokenIds, _availableRewards);
    }

    /**
     * @notice function called by the user to withdraw all NFTs and claim the rewards in one transaction
     */
    function withdrawAllNUTS() external {
        withdrawNUTS(stakers[Symbol.NUTS][msg.sender].stakedTokenIds);
        claimRewardsNUTS();
    }

    /* ========== ERC-20 STAKING ========== */

    function _checkERC20(Symbol _symbol) internal pure {
        require(
            _symbol == Symbol.NUT ||
                _symbol == Symbol.NUTS404 ||
                _symbol == Symbol.WEN ||
                _symbol == Symbol.NCASH,
            "Invalid ERC20 staked token symbol"
        );
    }

    /**
     * @notice If address has no Staker struct, initiate one. If address already was a stake,
     * calculate the rewards and add them to unclaimedRewards, reset the last time of
     * deposit and then add _amount to the already deposited amount.
     */
    function stakeERC20(Symbol _erc20, uint256 _amount) external {
        _checkERC20(_erc20);

        require(
            _amount >= minStake[_erc20],
            "Amount must be higher than minimimum deposit"
        );

        if (stakers[_erc20][msg.sender].staked == 0) {
            stakers[_erc20][msg.sender].timeOfLastUpdate = block.timestamp;
            stakers[_erc20][msg.sender].staked = _amount;
        } else {
            _updateUnclaimedRewards(_erc20);
            stakers[_erc20][msg.sender].staked += _amount;
        }
        IERC20(token[_erc20]).safeTransferFrom(
            msg.sender,
            address(this),
            _amount
        );
        totalStakedSupply[_erc20] += _amount;
        emit Staked(msg.sender, _erc20, _amount);
    }

    /**
     * @notice Withdraw specified amount of staked tokens
     */
    function withdrawERC20(Symbol _erc20, uint256 _amount) public {
        _checkERC20(_erc20);

        require(_amount > 0, "Amount must be greater than zero");

        require(
            stakers[_erc20][msg.sender].staked >= _amount,
            "Can't withdraw more than you have staked"
        );

        _updateUnclaimedRewards(_erc20);
        stakers[_erc20][msg.sender].staked -= _amount;

        IERC20(token[_erc20]).safeTransfer(msg.sender, _amount);
        totalStakedSupply[_erc20] -= _amount;
        emit Withdrawn(msg.sender, _erc20, _amount);
    }

    function claimRewardsERC20(Symbol _erc20) public {
        _checkERC20(_erc20);
        _claimRewards(_erc20);
    }

    function witrawAllERC20(Symbol _erc20) external {
        withdrawERC20(_erc20, stakers[_erc20][msg.sender].staked);
        claimRewardsERC20(_erc20);
    }

    /**
     * @notice Function used to get the info for a user: the ERC20 Token staked and the available Nutcash (NCASH) rewards.
     */
    function userStakeInfoERC20(
        Symbol _erc20,
        address _user
    ) external view returns (uint256 _stake, uint256 _availableRewards) {
        _checkERC20(_erc20);

        Staker memory _staker = stakers[_erc20][_user];
        _availableRewards =
            _staker.unclaimedRewards +
            calculateRewards(_erc20, _user);

        return (_staker.staked, _availableRewards);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"enum Nutcash.Symbol","name":"symbol","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"enum Nutcash.Symbol","name":"symbol","type":"uint8"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"enum Nutcash.Symbol","name":"symbol","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"enum Nutcash.Symbol","name":"symbol","type":"uint8"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"enum Nutcash.Symbol","name":"symbol","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HALVING_TIMESTAMP_1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HALVING_TIMESTAMP_2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HALVING_TIMESTAMP_3","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HALVING_TIMESTAMP_4","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PER_SECOND_0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PER_SECOND_1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PER_SECOND_2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PER_SECOND_3","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PER_SECOND_4","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","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":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"_erc20","type":"uint8"}],"name":"claimRewardsERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewardsNUTS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"","type":"uint8"}],"name":"minStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"","type":"uint8"}],"name":"rewardCoeffs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"_erc20","type":"uint8"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"stakeNUTS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakerAddressNUTS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakerToArrayIndexNUTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"}],"name":"stakers","outputs":[{"internalType":"uint256","name":"staked","type":"uint256"},{"internalType":"uint256","name":"timeOfLastUpdate","type":"uint256"},{"internalType":"uint256","name":"unclaimedRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakersArrayNUTS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"","type":"uint8"}],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdToArrayIndexNUTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"","type":"uint8"}],"name":"totalStakedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","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":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"_erc20","type":"uint8"},{"internalType":"address","name":"_user","type":"address"}],"name":"userStakeInfoERC20","outputs":[{"internalType":"uint256","name":"_stake","type":"uint256"},{"internalType":"uint256","name":"_availableRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"userStakeInfoNUTS","outputs":[{"internalType":"uint256[]","name":"_stakedTokenIds","type":"uint256[]"},{"internalType":"uint256","name":"_availableRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAllNUTS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"_erc20","type":"uint8"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"withdrawNUTS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Nutcash.Symbol","name":"_erc20","type":"uint8"}],"name":"witrawAllERC20","outputs":[],"stateMutability":"nonpayable","type":"function"}]

610160604052348015610010575f80fd5b506040518060400160405280600781526020017f4e75746361736800000000000000000000000000000000000000000000000000815250806040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600781526020017f4e757463617368000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f4e4341534800000000000000000000000000000000000000000000000000000081525081600390816100f99190610cf1565b5080600490816101099190610cf1565b5050506101206005836106fc60201b90919060201c565b610120818152505061013c6006826106fc60201b90919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a0818152505061017961074960201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050506101ee336101c96107a360201b60201c565b600a6101d59190610f28565b62a037a06101e39190610f72565b6107ab60201b60201c565b6402540be400600a5f80600481111561020a57610209610fb3565b5b600481111561021c5761021b610fb3565b5b81526020019081526020015f20819055506402540be400600a5f6001600481111561024a57610249610fb3565b5b600481111561025c5761025b610fb3565b5b81526020019081526020015f20819055506001600a5f6002600481111561028657610285610fb3565b5b600481111561029857610297610fb3565b5b81526020019081526020015f2081905550612710600a5f600360048111156102c3576102c2610fb3565b5b60048111156102d5576102d4610fb3565b5b81526020019081526020015f208190555062989680600a5f600480811115610300576102ff610fb3565b5b600481111561031257610311610fb3565b5b81526020019081526020015f208190555073a844cb1b558625c8a6214d460f2fcfa599eb464a600b5f80600481111561034e5761034d610fb3565b5b60048111156103605761035f610fb3565b5b81526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507337b2f564971d3bf986dc9e46ec587f42b75bde76600b5f600160048111156103d6576103d5610fb3565b5b60048111156103e8576103e7610fb3565b5b81526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550738697841b82c71fcbd9e58c15f6de68cd1c63fd02600b5f6002600481111561045e5761045d610fb3565b5b60048111156104705761046f610fb3565b5b81526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555073860ea9299e9c297fbde64143cab2a3cb01945a27600b5f600360048111156104e6576104e5610fb3565b5b60048111156104f8576104f7610fb3565b5b81526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555030600b5f60048081111561055957610558610fb3565b5b600481111561056b5761056a610fb3565b5b81526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600c5f8060048111156105cd576105cc610fb3565b5b60048111156105df576105de610fb3565b5b81526020019081526020015f208190555066038d7ea4c68000600c5f6001600481111561060f5761060e610fb3565b5b600481111561062157610620610fb3565b5b81526020019081526020015f2081905550670de0b6b3a7640000600c5f6002600481111561065257610651610fb3565b5b600481111561066457610663610fb3565b5b81526020019081526020015f208190555066038d7ea4c68000600c5f6003600481111561069457610693610fb3565b5b60048111156106a6576106a5610fb3565b5b81526020019081526020015f2081905550655af3107a4000600c5f6004808111156106d4576106d3610fb3565b5b60048111156106e6576106e5610fb3565b5b81526020019081526020015f208190555061124a565b5f60208351101561071d576107168361083060201b60201c565b9050610743565b8261072d8361089560201b60201c565b5f01908161073b9190610cf1565b5060ff5f1b90505b92915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e051610100514630604051602001610788959493929190611046565b60405160208183030381529060405280519060200120905090565b5f6012905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361081b575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016108129190611097565b60405180910390fd5b61082c5f838361089e60201b60201c565b5050565b5f80829050601f8151111561087c57826040517f305a27a90000000000000000000000000000000000000000000000000000000081526004016108739190611116565b60405180910390fd5b80518161088890611163565b5f1c175f1b915050919050565b5f819050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036108ee578060025f8282546108e291906111c9565b925050819055506109bc565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015610977578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161096e939291906111fc565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a03578060025f8282540392505081905550610a4d565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610aaa9190611231565b60405180910390a3505050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610b3257607f821691505b602082108103610b4557610b44610aee565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302610ba77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610b6c565b610bb18683610b6c565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f610bf5610bf0610beb84610bc9565b610bd2565b610bc9565b9050919050565b5f819050919050565b610c0e83610bdb565b610c22610c1a82610bfc565b848454610b78565b825550505050565b5f90565b610c36610c2a565b610c41818484610c05565b505050565b5b81811015610c6457610c595f82610c2e565b600181019050610c47565b5050565b601f821115610ca957610c7a81610b4b565b610c8384610b5d565b81016020851015610c92578190505b610ca6610c9e85610b5d565b830182610c46565b50505b505050565b5f82821c905092915050565b5f610cc95f1984600802610cae565b1980831691505092915050565b5f610ce18383610cba565b9150826002028217905092915050565b610cfa82610ab7565b67ffffffffffffffff811115610d1357610d12610ac1565b5b610d1d8254610b1b565b610d28828285610c68565b5f60209050601f831160018114610d59575f8415610d47578287015190505b610d518582610cd6565b865550610db8565b601f198416610d6786610b4b565b5f5b82811015610d8e57848901518255600182019150602085019450602081019050610d69565b86831015610dab5784890151610da7601f891682610cba565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f808291508390505b6001851115610e4257808604811115610e1e57610e1d610dc0565b5b6001851615610e2d5780820291505b8081029050610e3b85610ded565b9450610e02565b94509492505050565b5f82610e5a5760019050610f15565b81610e67575f9050610f15565b8160018114610e7d5760028114610e8757610eb6565b6001915050610f15565b60ff841115610e9957610e98610dc0565b5b8360020a915084821115610eb057610eaf610dc0565b5b50610f15565b5060208310610133831016604e8410600b8410161715610eeb5782820a905083811115610ee657610ee5610dc0565b5b610f15565b610ef88484846001610df9565b92509050818404811115610f0f57610f0e610dc0565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610f3282610bc9565b9150610f3d83610f1c565b9250610f6a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484610e4b565b905092915050565b5f610f7c82610bc9565b9150610f8783610bc9565b9250828202610f9581610bc9565b91508282048414831517610fac57610fab610dc0565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f819050919050565b610ff281610fe0565b82525050565b61100181610bc9565b82525050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61103082611007565b9050919050565b61104081611026565b82525050565b5f60a0820190506110595f830188610fe9565b6110666020830187610fe9565b6110736040830186610fe9565b6110806060830185610ff8565b61108d6080830184611037565b9695505050505050565b5f6020820190506110aa5f830184611037565b92915050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6110e882610ab7565b6110f281856110b0565b93506111028185602086016110c0565b61110b816110ce565b840191505092915050565b5f6020820190508181035f83015261112e81846110de565b905092915050565b5f81519050919050565b5f819050602082019050919050565b5f61115a8251610fe0565b80915050919050565b5f61116d82611136565b8261117784611140565b90506111828161114f565b925060208210156111c2576111bd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802610b6c565b831692505b5050919050565b5f6111d382610bc9565b91506111de83610bc9565b92508282019050808211156111f6576111f5610dc0565b5b92915050565b5f60608201905061120f5f830186611037565b61121c6020830185610ff8565b6112296040830184610ff8565b949350505050565b5f6020820190506112445f830184610ff8565b92915050565b60805160a05160c05160e051610100516101205161014051614f5661129b5f395f612dad01525f612d7201525f61344301525f61342201525f612b6f01525f612bc501525f612bee0152614f565ff3fe608060405234801561000f575f80fd5b506004361061027d575f3560e01c80635c69f7851161015a578063a0d63b6e116100cc578063cec5a01311610085578063cec5a013146107ce578063d505accf146107fe578063d7adf0ad1461081a578063d8c511551461084b578063dd62ed3e1461087b578063fd00ea1c146108ab5761027d565b8063a0d63b6e146106e2578063a9059cbb14610712578063b222dcdc14610742578063b22d2b5414610760578063b7bb0b9b1461077e578063ba9e50f6146107b05761027d565b80637b1fe3a51161011e5780637b1fe3a5146105f25780637ecebe0014610622578063841fe60b1461065257806384b0196e146106705780638e653d911461069457806395d89b41146106c45761027d565b80635c69f7851461053e57806370a082311461056e57806370eacfb41461059e57806375048ae1146105ba57806379cc6790146105d65761027d565b80632adcff15116101f35780633644e515116101b75780633644e515146104a05780633c9cc98f146104be5780633f5b6566146104dc57806342966c68146104fa5780634e3d97c3146105165780635a8bc18e146105205761027d565b80632adcff151461040c5780632e3a6f1f1461042a578063312c3f6114610448578063313ce5671461046457806332cb6b0c146104825761027d565b8063150b7a0211610245578063150b7a021461033757806318160ddd1461036757806320c09e7c1461038557806322246c9b1461038f57806323b872dd146103c05780632650bef5146103f05761027d565b80630104e8791461028157806306fdde031461029d578063095ea7b3146102bb578063098d6e82146102eb5780630da8d6041461031b575b5f80fd5b61029b60048036038101906102969190613aaa565b6108db565b005b6102a5610d27565b6040516102b29190613b65565b60405180910390f35b6102d560048036038101906102d09190613c12565b610db7565b6040516102e29190613c6a565b60405180910390f35b61030560048036038101906103009190613c83565b610dd9565b6040516103129190613cbd565b60405180910390f35b61033560048036038101906103309190613cf9565b610dee565b005b610351600480360381019061034c9190613e5f565b61109d565b60405161035e9190613f19565b60405180910390f35b61036f6110b0565b60405161037c9190613cbd565b60405180910390f35b61038d6110b9565b005b6103a960048036038101906103a49190613c83565b6110c4565b6040516103b7929190613fe9565b60405180910390f35b6103da60048036038101906103d59190614017565b6111f7565b6040516103e79190613c6a565b60405180910390f35b61040a60048036038101906104059190614067565b611225565b005b6104146112ad565b6040516104219190613cbd565b60405180910390f35b6104326112b2565b60405161043f9190613cbd565b60405180910390f35b610462600480360381019061045d9190614067565b6112ba565b005b61046c6112cf565b60405161047991906140ad565b60405180910390f35b61048a6112d7565b6040516104979190613cbd565b60405180910390f35b6104a86112e6565b6040516104b591906140de565b60405180910390f35b6104c66112f4565b6040516104d39190613cbd565b60405180910390f35b6104e46112fc565b6040516104f19190613cbd565b60405180910390f35b610514600480360381019061050f91906140f7565b611301565b005b61051e611315565b005b6105286113e7565b6040516105359190613cbd565b60405180910390f35b610558600480360381019061055391906140f7565b6113ec565b6040516105659190614131565b60405180910390f35b61058860048036038101906105839190613c83565b611427565b6040516105959190613cbd565b60405180910390f35b6105b860048036038101906105b39190613cf9565b61146c565b005b6105d460048036038101906105cf919061420a565b61180c565b005b6105f060048036038101906105eb9190613c12565b611e5f565b005b61060c600480360381019061060791906140f7565b611e7f565b6040516106199190614131565b60405180910390f35b61063c60048036038101906106379190613c83565b611eaf565b6040516106499190613cbd565b60405180910390f35b61065a611ec0565b6040516106679190613cbd565b60405180910390f35b610678611ec8565b60405161068b979695949392919061428b565b60405180910390f35b6106ae60048036038101906106a99190614067565b611f6d565b6040516106bb9190613cbd565b60405180910390f35b6106cc611f82565b6040516106d99190613b65565b60405180910390f35b6106fc60048036038101906106f791906140f7565b612012565b6040516107099190613cbd565b60405180910390f35b61072c60048036038101906107279190613c12565b612027565b6040516107399190613c6a565b60405180910390f35b61074a612049565b6040516107579190613cbd565b60405180910390f35b610768612051565b6040516107759190613cbd565b60405180910390f35b6107986004803603810190610793919061430d565b612056565b6040516107a79392919061434b565b60405180910390f35b6107b8612087565b6040516107c59190613cbd565b60405180910390f35b6107e860048036038101906107e39190614067565b61208c565b6040516107f59190613cbd565b60405180910390f35b610818600480360381019061081391906143d4565b6120a1565b005b610834600480360381019061082f919061430d565b6121e6565b604051610842929190614471565b60405180910390f35b61086560048036038101906108609190614067565b61230b565b6040516108729190613cbd565b60405180910390f35b61089560048036038101906108909190614498565b612320565b6040516108a29190613cbd565b60405180910390f35b6108c560048036038101906108c09190614067565b6123a2565b6040516108d29190614131565b60405180910390f35b600c5f8060048111156108f1576108f06144d6565b5b6004811115610903576109026144d6565b5b81526020019081526020015f2054828290501015610956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094d90614573565b60405180910390fd5b5f60085f80600481111561096d5761096c6144d6565b5b600481111561097f5761097e6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f816001018054905011156109e6576109e15f6123d2565b610aa3565b600e33908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600e80549050610a5891906145be565b600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055504281600201819055505b5f8383905090505f5b81811015610c8357600b5f806004811115610aca57610ac96144d6565b5b6004811115610adc57610adb6144d6565b5b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3330888886818110610b3957610b386145f1565b5b905060200201356040518463ffffffff1660e01b8152600401610b5e9392919061461e565b5f604051808303815f87803b158015610b75575f80fd5b505af1158015610b87573d5f803e3d5ffd5b5050505082600101858583818110610ba257610ba16145f1565b5b90506020020135908060018154018082558091505060019003905f5260205f20015f909190919091505560018360010180549050610be091906145be565b60105f878785818110610bf657610bf56145f1565b5b9050602002013581526020019081526020015f208190555033600d5f878785818110610c2557610c246145f1565b5b9050602002013581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508080600101915050610aac565b508060095f806004811115610c9b57610c9a6144d6565b5b6004811115610cad57610cac6144d6565b5b81526020019081526020015f205f828254610cc89190614653565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f684aec4c92b52f473a97bed4ba4b04707b216b94099c51e5170c71d31ff569ea5f8686604051610d1993929190614734565b60405180910390a250505050565b606060038054610d3690614791565b80601f0160208091040260200160405190810160405280929190818152602001828054610d6290614791565b8015610dad5780601f10610d8457610100808354040283529160200191610dad565b820191905f5260205f20905b815481529060010190602001808311610d9057829003601f168201915b5050505050905090565b5f80610dc1612475565b9050610dce81858561247c565b600191505092915050565b600f602052805f5260405f205f915090505481565b610df78261248e565b5f8111610e39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e309061480b565b60405180910390fd5b8060085f846004811115610e5057610e4f6144d6565b5b6004811115610e6257610e616144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01541015610eee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee590614899565b60405180910390fd5b610ef7826123d2565b8060085f846004811115610f0e57610f0d6144d6565b5b6004811115610f2057610f1f6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f828254610f7891906145be565b92505081905550610ffe3382600b5f866004811115610f9a57610f996144d6565b5b6004811115610fac57610fab6144d6565b5b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125849092919063ffffffff16565b8060095f846004811115611015576110146144d6565b5b6004811115611027576110266144d6565b5b81526020019081526020015f205f82825461104291906145be565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f83637d0d125e3dae88720b1ad229ce05c339c065b6282caf315dcb35a999d6d483836040516110919291906148b7565b60405180910390a25050565b5f63150b7a0260e01b9050949350505050565b5f600254905090565b6110c25f612603565b565b60605f8060085f8060048111156110de576110dd6144d6565b5b60048111156110f0576110ef6144d6565b5b81526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060800160405290815f82015481526020016001820180548060200260200160405190810160405280929190818152602001828054801561119957602002820191905f5260205f20905b815481526020019060010190808311611185575b505050505081526020016002820154815260200160038201548152505090505f816020015151146111e2576111ce5f85612797565b81606001516111dd9190614653565b6111e8565b80606001515b91508060200151925050915091565b5f80611201612475565b905061120e8582856129ea565b611219858585612a7c565b60019150509392505050565b6112a18160085f84600481111561123f5761123e6144d6565b5b6004811115611251576112506144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0154610dee565b6112aa816112ba565b50565b601481565b637c9d3d3081565b6112c38161248e565b6112cc81612603565b50565b5f6012905090565b6a115eec47f6cf7e3500000081565b5f6112ef612b6c565b905090565b636d90fe3081565b60a081565b61131261130c612475565b82612c22565b50565b6113dd60085f80600481111561132e5761132d6144d6565b5b60048111156113405761133f6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206001018054806020026020016040519081016040528092919081815260200182805480156113d357602002820191905f5260205f20905b8154815260200190600101908083116113bf575b505050505061180c565b6113e56110b9565b565b602881565b600e81815481106113fb575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6114758261248e565b600c5f83600481111561148b5761148a6144d6565b5b600481111561149d5761149c6144d6565b5b81526020019081526020015f20548110156114ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e49061494e565b60405180910390fd5b5f60085f846004811115611504576115036144d6565b5b6004811115611516576115156144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01540361165a574260085f84600481111561157d5761157c6144d6565b5b600481111561158f5761158e6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600201819055508060085f8460048111156115f5576115f46144d6565b5b6004811115611607576116066144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01819055506116ec565b611663826123d2565b8060085f84600481111561167a576116796144d6565b5b600481111561168c5761168b6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282546116e49190614653565b925050819055505b61176d333083600b5f876004811115611708576117076144d6565b5b600481111561171a576117196144d6565b5b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ca1909392919063ffffffff16565b8060095f846004811115611784576117836144d6565b5b6004811115611796576117956144d6565b5b81526020019081526020015f205f8282546117b19190614653565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f3cf14181ae25669a913d72411736fc5c01f538fa503e963b0b2e56bcefb3edaf83836040516118009291906148b7565b60405180910390a25050565b5f81510361184f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611846906149b6565b60405180910390fd5b5f60085f806004811115611866576118656144d6565b5b6004811115611878576118776144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f81600101805490501161190b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190290614a1e565b60405180910390fd5b6119145f6123d2565b5f825190505f5b81811015611bf9573373ffffffffffffffffffffffffffffffffffffffff16600d5f8684815181106119505761194f6145f1565b5b602002602001015181526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d290614a86565b60405180910390fd5b5f60105f8684815181106119f2576119f16145f1565b5b602002602001015181526020019081526020015f205490505f60018560010180549050611a1f91906145be565b9050808214611a9e57846001018181548110611a3e57611a3d6145f1565b5b905f5260205f200154856001018381548110611a5d57611a5c6145f1565b5b905f5260205f2001819055508160105f876001018581548110611a8357611a826145f1565b5b905f5260205f20015481526020019081526020015f20819055505b84600101805480611ab257611ab1614aa4565b5b600190038181905f5260205f20015f90559055600d5f878581518110611adb57611ada6145f1565b5b602002602001015181526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600b5f806004811115611b2857611b276144d6565b5b6004811115611b3a57611b396144d6565b5b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3033898781518110611b9757611b966145f1565b5b60200260200101516040518463ffffffff1660e01b8152600401611bbd9392919061461e565b5f604051808303815f87803b158015611bd4575f80fd5b505af1158015611be6573d5f803e3d5ffd5b505050508280600101935050505061191b565b508060095f806004811115611c1157611c106144d6565b5b6004811115611c2357611c226144d6565b5b81526020019081526020015f205f828254611c3e91906145be565b925050819055505f826001018054905003611e0a575f600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f6001600e80549050611ca791906145be565b9050808214611dc357600e8181548110611cc457611cc36145f1565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600e8381548110611d0057611cff6145f1565b5b905f5260205f20015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600f5f600e8581548110611d5d57611d5c6145f1565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b600e805480611dd557611dd4614aa4565b5b600190038181905f5260205f20015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055905550505b3373ffffffffffffffffffffffffffffffffffffffff167f26d429555a03b06a860d74ebe69930a09a0b7f4d37eca0ea63d37385b3d015e65f85604051611e52929190614ad1565b60405180910390a2505050565b611e7182611e6b612475565b836129ea565b611e7b8282612c22565b5050565b600d602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f611eb982612d23565b9050919050565b6375171db081565b5f6060805f805f6060611ed9612d69565b611ee1612da4565b46305f801b5f67ffffffffffffffff811115611f0057611eff613d3b565b5b604051908082528060200260200182016040528015611f2e5781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b6009602052805f5260405f205f915090505481565b606060048054611f9190614791565b80601f0160208091040260200160405190810160405280929190818152602001828054611fbd90614791565b80156120085780601f10611fdf57610100808354040283529160200191612008565b820191905f5260205f20905b815481529060010190602001808311611feb57829003601f168201915b5050505050905090565b6010602052805f5260405f205f915090505481565b5f80612031612475565b905061203e818585612a7c565b600191505092915050565b6384235cb081565b600a81565b6008602052815f5260405f20602052805f5260405f205f9150915050805f0154908060020154908060030154905083565b605081565b600a602052805f5260405f205f915090505481565b834211156120e657836040517f627913020000000000000000000000000000000000000000000000000000000081526004016120dd9190613cbd565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886121148c612ddf565b8960405160200161212a96959493929190614aff565b6040516020818303038152906040528051906020012090505f61214c82612e32565b90505f61215b82878787612e4b565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146121cf57808a6040517f4b800e460000000000000000000000000000000000000000000000000000000081526004016121c6929190614b5e565b60405180910390fd5b6121da8a8a8a61247c565b50505050505050505050565b5f806121f18461248e565b5f60085f866004811115612208576122076144d6565b5b600481111561221a576122196144d6565b5b81526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060800160405290815f8201548152602001600182018054806020026020016040519081016040528092919081815260200182805480156122c357602002820191905f5260205f20905b8154815260200190600101908083116122af575b505050505081526020016002820154815260200160038201548152505090506122ec8585612797565b81606001516122fb9190614653565b9150805f01519250509250929050565b600c602052805f5260405f205f915090505481565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b600b602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60085f8360048111156123e9576123e86144d6565b5b60048111156123fb576123fa6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20905061244f8233612797565b816003015f8282546124619190614653565b925050819055504281600201819055505050565b5f33905090565b6124898383836001612e79565b505050565b600260048111156124a2576124a16144d6565b5b8160048111156124b5576124b46144d6565b5b14806124e55750600160048111156124d0576124cf6144d6565b5b8160048111156124e3576124e26144d6565b5b145b806125145750600360048111156124ff576124fe6144d6565b5b816004811115612512576125116144d6565b5b145b80612542575060048081111561252d5761252c6144d6565b5b8160048111156125405761253f6144d6565b5b145b612581576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257890614bf5565b60405180910390fd5b50565b6125fe838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016125b7929190614c13565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613048565b505050565b5f60085f83600481111561261a576126196144d6565b5b600481111561262c5761262b6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600301546126828333612797565b61268c9190614653565b90505f81116126d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126c790614c84565b60405180910390fd5b6a115eec47f6cf7e35000000816126e56110b0565b6126ef9190614653565b1115612730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161272790614cec565b60405180910390fd5b612739826130dd565b6127433382613166565b3373ffffffffffffffffffffffffffffffffffffffff167f721da0e761006d69a1240bd9ca78df4c4cb651e29fde11b2702993c175eadd5a838360405161278b9291906148b7565b60405180910390a25050565b5f8060085f8560048111156127af576127ae6144d6565b5b60048111156127c1576127c06144d6565b5b81526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060800160405290815f82015481526020016001820180548060200260200160405190810160405280929190818152602001828054801561286a57602002820191905f5260205f20905b815481526020019060010190808311612856575b505050505081526020016002820154815260200160038201548152505090505f636d90fe3042101561289f5760a090506128e6565b6375171db04210156128b457605090506128e5565b637c9d3d304210156128c957602890506128e4565b6384235cb04210156128de57601490506128e3565b600a90505b5b5b5b5f8060048111156128fa576128f96144d6565b5b86600481111561290d5761290c6144d6565b5b0361291d57826020015151612922565b825f01515b90505f806004811115612938576129376144d6565b5b87600481111561294b5761294a6144d6565b5b03612957576001612961565b670de0b6b3a76400005b67ffffffffffffffff16905080600a5f896004811115612984576129836144d6565b5b6004811115612996576129956144d6565b5b81526020019081526020015f205484848760400151426129b691906145be565b6129c09190614d0a565b6129ca9190614d0a565b6129d49190614d0a565b6129de9190614d78565b94505050505092915050565b5f6129f58484612320565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612a765781811015612a67578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401612a5e93929190614da8565b60405180910390fd5b612a7584848484035f612e79565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612aec575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401612ae39190614131565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612b5c575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401612b539190614131565b60405180910390fd5b612b678383836131e5565b505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015612be757507f000000000000000000000000000000000000000000000000000000000000000046145b15612c14577f00000000000000000000000000000000000000000000000000000000000000009050612c1f565b612c1c6133fe565b90505b90565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612c92575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401612c899190614131565b60405180910390fd5b612c9d825f836131e5565b5050565b612d1d848573ffffffffffffffffffffffffffffffffffffffff166323b872dd868686604051602401612cd69392919061461e565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613048565b50505050565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6060612d9f60057f000000000000000000000000000000000000000000000000000000000000000061349390919063ffffffff16565b905090565b6060612dda60067f000000000000000000000000000000000000000000000000000000000000000061349390919063ffffffff16565b905090565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f612e44612e3e612b6c565b83613540565b9050919050565b5f805f80612e5b88888888613580565b925092509250612e6b8282613667565b829350505050949350505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612ee9575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401612ee09190614131565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612f59575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401612f509190614131565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015613042578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516130399190613cbd565b60405180910390a35b50505050565b5f613072828473ffffffffffffffffffffffffffffffffffffffff166137c990919063ffffffff16565b90505f8151141580156130965750808060200190518101906130949190614e07565b155b156130d857826040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016130cf9190614131565b60405180910390fd5b505050565b5f60085f8360048111156130f4576130f36144d6565b5b6004811115613106576131056144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f81600301819055504281600201819055505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036131d6575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016131cd9190614131565b60405180910390fd5b6131e15f83836131e5565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613235578060025f8282546132299190614653565b92505081905550613303565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156132be578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016132b593929190614da8565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361334a578060025f8282540392505081905550613394565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516133f19190613cbd565b60405180910390a3505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000004630604051602001613478959493929190614e32565b60405160208183030381529060405280519060200120905090565b606060ff5f1b83146134af576134a8836137de565b905061353a565b8180546134bb90614791565b80601f01602080910402602001604051908101604052809291908181526020018280546134e790614791565b80156135325780601f1061350957610100808354040283529160200191613532565b820191905f5260205f20905b81548152906001019060200180831161351557829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c11156135bc575f60038592509250925061365d565b5f6001888888886040515f81526020016040526040516135df9493929190614e83565b6020604051602081039080840390855afa1580156135ff573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613650575f60015f801b9350935093505061365d565b805f805f1b935093509350505b9450945094915050565b5f600381111561367a576136796144d6565b5b82600381111561368d5761368c6144d6565b5b03156137c557600160038111156136a7576136a66144d6565b5b8260038111156136ba576136b96144d6565b5b036136f1576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115613705576137046144d6565b5b826003811115613718576137176144d6565b5b0361375c57805f1c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016137539190613cbd565b60405180910390fd5b60038081111561376f5761376e6144d6565b5b826003811115613782576137816144d6565b5b036137c457806040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004016137bb91906140de565b60405180910390fd5b5b5050565b60606137d683835f613850565b905092915050565b60605f6137ea83613919565b90505f602067ffffffffffffffff81111561380857613807613d3b565b5b6040519080825280601f01601f19166020018201604052801561383a5781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b60608147101561389757306040517fcd78605900000000000000000000000000000000000000000000000000000000815260040161388e9190614131565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff1684866040516138bf9190614f0a565b5f6040518083038185875af1925050503d805f81146138f9576040519150601f19603f3d011682016040523d82523d5f602084013e6138fe565b606091505b509150915061390e868383613967565b925050509392505050565b5f8060ff835f1c169050601f81111561395e576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b60608261397c57613977826139f4565b6139ec565b5f82511480156139a257505f8473ffffffffffffffffffffffffffffffffffffffff163b145b156139e457836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016139db9190614131565b60405180910390fd5b8190506139ed565b5b9392505050565b5f81511115613a065780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112613a6a57613a69613a49565b5b8235905067ffffffffffffffff811115613a8757613a86613a4d565b5b602083019150836020820283011115613aa357613aa2613a51565b5b9250929050565b5f8060208385031215613ac057613abf613a41565b5b5f83013567ffffffffffffffff811115613add57613adc613a45565b5b613ae985828601613a55565b92509250509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613b3782613af5565b613b418185613aff565b9350613b51818560208601613b0f565b613b5a81613b1d565b840191505092915050565b5f6020820190508181035f830152613b7d8184613b2d565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613bae82613b85565b9050919050565b613bbe81613ba4565b8114613bc8575f80fd5b50565b5f81359050613bd981613bb5565b92915050565b5f819050919050565b613bf181613bdf565b8114613bfb575f80fd5b50565b5f81359050613c0c81613be8565b92915050565b5f8060408385031215613c2857613c27613a41565b5b5f613c3585828601613bcb565b9250506020613c4685828601613bfe565b9150509250929050565b5f8115159050919050565b613c6481613c50565b82525050565b5f602082019050613c7d5f830184613c5b565b92915050565b5f60208284031215613c9857613c97613a41565b5b5f613ca584828501613bcb565b91505092915050565b613cb781613bdf565b82525050565b5f602082019050613cd05f830184613cae565b92915050565b60058110613ce2575f80fd5b50565b5f81359050613cf381613cd6565b92915050565b5f8060408385031215613d0f57613d0e613a41565b5b5f613d1c85828601613ce5565b9250506020613d2d85828601613bfe565b9150509250929050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613d7182613b1d565b810181811067ffffffffffffffff82111715613d9057613d8f613d3b565b5b80604052505050565b5f613da2613a38565b9050613dae8282613d68565b919050565b5f67ffffffffffffffff821115613dcd57613dcc613d3b565b5b613dd682613b1d565b9050602081019050919050565b828183375f83830152505050565b5f613e03613dfe84613db3565b613d99565b905082815260208101848484011115613e1f57613e1e613d37565b5b613e2a848285613de3565b509392505050565b5f82601f830112613e4657613e45613a49565b5b8135613e56848260208601613df1565b91505092915050565b5f805f8060808587031215613e7757613e76613a41565b5b5f613e8487828801613bcb565b9450506020613e9587828801613bcb565b9350506040613ea687828801613bfe565b925050606085013567ffffffffffffffff811115613ec757613ec6613a45565b5b613ed387828801613e32565b91505092959194509250565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613f1381613edf565b82525050565b5f602082019050613f2c5f830184613f0a565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613f6481613bdf565b82525050565b5f613f758383613f5b565b60208301905092915050565b5f602082019050919050565b5f613f9782613f32565b613fa18185613f3c565b9350613fac83613f4c565b805f5b83811015613fdc578151613fc38882613f6a565b9750613fce83613f81565b925050600181019050613faf565b5085935050505092915050565b5f6040820190508181035f8301526140018185613f8d565b90506140106020830184613cae565b9392505050565b5f805f6060848603121561402e5761402d613a41565b5b5f61403b86828701613bcb565b935050602061404c86828701613bcb565b925050604061405d86828701613bfe565b9150509250925092565b5f6020828403121561407c5761407b613a41565b5b5f61408984828501613ce5565b91505092915050565b5f60ff82169050919050565b6140a781614092565b82525050565b5f6020820190506140c05f83018461409e565b92915050565b5f819050919050565b6140d8816140c6565b82525050565b5f6020820190506140f15f8301846140cf565b92915050565b5f6020828403121561410c5761410b613a41565b5b5f61411984828501613bfe565b91505092915050565b61412b81613ba4565b82525050565b5f6020820190506141445f830184614122565b92915050565b5f67ffffffffffffffff82111561416457614163613d3b565b5b602082029050602081019050919050565b5f6141876141828461414a565b613d99565b905080838252602082019050602084028301858111156141aa576141a9613a51565b5b835b818110156141d357806141bf8882613bfe565b8452602084019350506020810190506141ac565b5050509392505050565b5f82601f8301126141f1576141f0613a49565b5b8135614201848260208601614175565b91505092915050565b5f6020828403121561421f5761421e613a41565b5b5f82013567ffffffffffffffff81111561423c5761423b613a45565b5b614248848285016141dd565b91505092915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b61428581614251565b82525050565b5f60e08201905061429e5f83018a61427c565b81810360208301526142b08189613b2d565b905081810360408301526142c48188613b2d565b90506142d36060830187613cae565b6142e06080830186614122565b6142ed60a08301856140cf565b81810360c08301526142ff8184613f8d565b905098975050505050505050565b5f806040838503121561432357614322613a41565b5b5f61433085828601613ce5565b925050602061434185828601613bcb565b9150509250929050565b5f60608201905061435e5f830186613cae565b61436b6020830185613cae565b6143786040830184613cae565b949350505050565b61438981614092565b8114614393575f80fd5b50565b5f813590506143a481614380565b92915050565b6143b3816140c6565b81146143bd575f80fd5b50565b5f813590506143ce816143aa565b92915050565b5f805f805f805f60e0888a0312156143ef576143ee613a41565b5b5f6143fc8a828b01613bcb565b975050602061440d8a828b01613bcb565b965050604061441e8a828b01613bfe565b955050606061442f8a828b01613bfe565b94505060806144408a828b01614396565b93505060a06144518a828b016143c0565b92505060c06144628a828b016143c0565b91505092959891949750929550565b5f6040820190506144845f830185613cae565b6144916020830184613cae565b9392505050565b5f80604083850312156144ae576144ad613a41565b5b5f6144bb85828601613bcb565b92505060206144cc85828601613bcb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b7f546f6b656e206e756d626572206d75737420626520686967686572207468616e5f8201527f206d696e696d696d756d206465706f7369740000000000000000000000000000602082015250565b5f61455d603283613aff565b915061456882614503565b604082019050919050565b5f6020820190508181035f83015261458a81614551565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6145c882613bdf565b91506145d383613bdf565b92508282039050818111156145eb576145ea614591565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6060820190506146315f830186614122565b61463e6020830185614122565b61464b6040830184613cae565b949350505050565b5f61465d82613bdf565b915061466883613bdf565b92508282019050808211156146805761467f614591565b5b92915050565b60058110614697576146966144d6565b5b50565b5f8190506146a782614686565b919050565b5f6146b68261469a565b9050919050565b6146c6816146ac565b82525050565b5f80fd5b82818337505050565b5f6146e48385613f3c565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115614717576147166146cc565b5b6020830292506147288385846146d0565b82840190509392505050565b5f6040820190506147475f8301866146bd565b818103602083015261475a8184866146d9565b9050949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806147a857607f821691505b6020821081036147bb576147ba614764565b5b50919050565b7f416d6f756e74206d7573742062652067726561746572207468616e207a65726f5f82015250565b5f6147f5602083613aff565b9150614800826147c1565b602082019050919050565b5f6020820190508181035f830152614822816147e9565b9050919050565b7f43616e2774207769746864726177206d6f7265207468616e20796f75206861765f8201527f65207374616b6564000000000000000000000000000000000000000000000000602082015250565b5f614883602883613aff565b915061488e82614829565b604082019050919050565b5f6020820190508181035f8301526148b081614877565b9050919050565b5f6040820190506148ca5f8301856146bd565b6148d76020830184613cae565b9392505050565b7f416d6f756e74206d75737420626520686967686572207468616e206d696e696d5f8201527f696d756d206465706f7369740000000000000000000000000000000000000000602082015250565b5f614938602c83613aff565b9150614943826148de565b604082019050919050565b5f6020820190508181035f8301526149658161492c565b9050919050565b7f4e6f20746f6b656e4964732070726f76696465640000000000000000000000005f82015250565b5f6149a0601483613aff565b91506149ab8261496c565b602082019050919050565b5f6020820190508181035f8301526149cd81614994565b9050919050565b7f4e6f20746f6b656e73207374616b656420746f207769746864726177000000005f82015250565b5f614a08601c83613aff565b9150614a13826149d4565b602082019050919050565b5f6020820190508181035f830152614a35816149fc565b9050919050565b7f4e6f7420746865207374616b6572206f662074686520746f6b656e00000000005f82015250565b5f614a70601b83613aff565b9150614a7b82614a3c565b602082019050919050565b5f6020820190508181035f830152614a9d81614a64565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f604082019050614ae45f8301856146bd565b8181036020830152614af68184613f8d565b90509392505050565b5f60c082019050614b125f8301896140cf565b614b1f6020830188614122565b614b2c6040830187614122565b614b396060830186613cae565b614b466080830185613cae565b614b5360a0830184613cae565b979650505050505050565b5f604082019050614b715f830185614122565b614b7e6020830184614122565b9392505050565b7f496e76616c6964204552433230207374616b656420746f6b656e2073796d626f5f8201527f6c00000000000000000000000000000000000000000000000000000000000000602082015250565b5f614bdf602183613aff565b9150614bea82614b85565b604082019050919050565b5f6020820190508181035f830152614c0c81614bd3565b9050919050565b5f604082019050614c265f830185614122565b614c336020830184613cae565b9392505050565b7f4e6f207265776172647320746f20636c61696d000000000000000000000000005f82015250565b5f614c6e601383613aff565b9150614c7982614c3a565b602082019050919050565b5f6020820190508181035f830152614c9b81614c62565b9050919050565b7f45786365656473204d41585f535550504c5900000000000000000000000000005f82015250565b5f614cd6601283613aff565b9150614ce182614ca2565b602082019050919050565b5f6020820190508181035f830152614d0381614cca565b9050919050565b5f614d1482613bdf565b9150614d1f83613bdf565b9250828202614d2d81613bdf565b91508282048414831517614d4457614d43614591565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614d8282613bdf565b9150614d8d83613bdf565b925082614d9d57614d9c614d4b565b5b828204905092915050565b5f606082019050614dbb5f830186614122565b614dc86020830185613cae565b614dd56040830184613cae565b949350505050565b614de681613c50565b8114614df0575f80fd5b50565b5f81519050614e0181614ddd565b92915050565b5f60208284031215614e1c57614e1b613a41565b5b5f614e2984828501614df3565b91505092915050565b5f60a082019050614e455f8301886140cf565b614e5260208301876140cf565b614e5f60408301866140cf565b614e6c6060830185613cae565b614e796080830184614122565b9695505050505050565b5f608082019050614e965f8301876140cf565b614ea3602083018661409e565b614eb060408301856140cf565b614ebd60608301846140cf565b95945050505050565b5f81519050919050565b5f81905092915050565b5f614ee482614ec6565b614eee8185614ed0565b9350614efe818560208601613b0f565b80840191505092915050565b5f614f158284614eda565b91508190509291505056fea2646970667358221220ac2268774346f622e49c4b552a07268603e4669d074afd830f259c3c471245b364736f6c63430008190033

Deployed Bytecode

0x608060405234801561000f575f80fd5b506004361061027d575f3560e01c80635c69f7851161015a578063a0d63b6e116100cc578063cec5a01311610085578063cec5a013146107ce578063d505accf146107fe578063d7adf0ad1461081a578063d8c511551461084b578063dd62ed3e1461087b578063fd00ea1c146108ab5761027d565b8063a0d63b6e146106e2578063a9059cbb14610712578063b222dcdc14610742578063b22d2b5414610760578063b7bb0b9b1461077e578063ba9e50f6146107b05761027d565b80637b1fe3a51161011e5780637b1fe3a5146105f25780637ecebe0014610622578063841fe60b1461065257806384b0196e146106705780638e653d911461069457806395d89b41146106c45761027d565b80635c69f7851461053e57806370a082311461056e57806370eacfb41461059e57806375048ae1146105ba57806379cc6790146105d65761027d565b80632adcff15116101f35780633644e515116101b75780633644e515146104a05780633c9cc98f146104be5780633f5b6566146104dc57806342966c68146104fa5780634e3d97c3146105165780635a8bc18e146105205761027d565b80632adcff151461040c5780632e3a6f1f1461042a578063312c3f6114610448578063313ce5671461046457806332cb6b0c146104825761027d565b8063150b7a0211610245578063150b7a021461033757806318160ddd1461036757806320c09e7c1461038557806322246c9b1461038f57806323b872dd146103c05780632650bef5146103f05761027d565b80630104e8791461028157806306fdde031461029d578063095ea7b3146102bb578063098d6e82146102eb5780630da8d6041461031b575b5f80fd5b61029b60048036038101906102969190613aaa565b6108db565b005b6102a5610d27565b6040516102b29190613b65565b60405180910390f35b6102d560048036038101906102d09190613c12565b610db7565b6040516102e29190613c6a565b60405180910390f35b61030560048036038101906103009190613c83565b610dd9565b6040516103129190613cbd565b60405180910390f35b61033560048036038101906103309190613cf9565b610dee565b005b610351600480360381019061034c9190613e5f565b61109d565b60405161035e9190613f19565b60405180910390f35b61036f6110b0565b60405161037c9190613cbd565b60405180910390f35b61038d6110b9565b005b6103a960048036038101906103a49190613c83565b6110c4565b6040516103b7929190613fe9565b60405180910390f35b6103da60048036038101906103d59190614017565b6111f7565b6040516103e79190613c6a565b60405180910390f35b61040a60048036038101906104059190614067565b611225565b005b6104146112ad565b6040516104219190613cbd565b60405180910390f35b6104326112b2565b60405161043f9190613cbd565b60405180910390f35b610462600480360381019061045d9190614067565b6112ba565b005b61046c6112cf565b60405161047991906140ad565b60405180910390f35b61048a6112d7565b6040516104979190613cbd565b60405180910390f35b6104a86112e6565b6040516104b591906140de565b60405180910390f35b6104c66112f4565b6040516104d39190613cbd565b60405180910390f35b6104e46112fc565b6040516104f19190613cbd565b60405180910390f35b610514600480360381019061050f91906140f7565b611301565b005b61051e611315565b005b6105286113e7565b6040516105359190613cbd565b60405180910390f35b610558600480360381019061055391906140f7565b6113ec565b6040516105659190614131565b60405180910390f35b61058860048036038101906105839190613c83565b611427565b6040516105959190613cbd565b60405180910390f35b6105b860048036038101906105b39190613cf9565b61146c565b005b6105d460048036038101906105cf919061420a565b61180c565b005b6105f060048036038101906105eb9190613c12565b611e5f565b005b61060c600480360381019061060791906140f7565b611e7f565b6040516106199190614131565b60405180910390f35b61063c60048036038101906106379190613c83565b611eaf565b6040516106499190613cbd565b60405180910390f35b61065a611ec0565b6040516106679190613cbd565b60405180910390f35b610678611ec8565b60405161068b979695949392919061428b565b60405180910390f35b6106ae60048036038101906106a99190614067565b611f6d565b6040516106bb9190613cbd565b60405180910390f35b6106cc611f82565b6040516106d99190613b65565b60405180910390f35b6106fc60048036038101906106f791906140f7565b612012565b6040516107099190613cbd565b60405180910390f35b61072c60048036038101906107279190613c12565b612027565b6040516107399190613c6a565b60405180910390f35b61074a612049565b6040516107579190613cbd565b60405180910390f35b610768612051565b6040516107759190613cbd565b60405180910390f35b6107986004803603810190610793919061430d565b612056565b6040516107a79392919061434b565b60405180910390f35b6107b8612087565b6040516107c59190613cbd565b60405180910390f35b6107e860048036038101906107e39190614067565b61208c565b6040516107f59190613cbd565b60405180910390f35b610818600480360381019061081391906143d4565b6120a1565b005b610834600480360381019061082f919061430d565b6121e6565b604051610842929190614471565b60405180910390f35b61086560048036038101906108609190614067565b61230b565b6040516108729190613cbd565b60405180910390f35b61089560048036038101906108909190614498565b612320565b6040516108a29190613cbd565b60405180910390f35b6108c560048036038101906108c09190614067565b6123a2565b6040516108d29190614131565b60405180910390f35b600c5f8060048111156108f1576108f06144d6565b5b6004811115610903576109026144d6565b5b81526020019081526020015f2054828290501015610956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094d90614573565b60405180910390fd5b5f60085f80600481111561096d5761096c6144d6565b5b600481111561097f5761097e6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f816001018054905011156109e6576109e15f6123d2565b610aa3565b600e33908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600e80549050610a5891906145be565b600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055504281600201819055505b5f8383905090505f5b81811015610c8357600b5f806004811115610aca57610ac96144d6565b5b6004811115610adc57610adb6144d6565b5b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3330888886818110610b3957610b386145f1565b5b905060200201356040518463ffffffff1660e01b8152600401610b5e9392919061461e565b5f604051808303815f87803b158015610b75575f80fd5b505af1158015610b87573d5f803e3d5ffd5b5050505082600101858583818110610ba257610ba16145f1565b5b90506020020135908060018154018082558091505060019003905f5260205f20015f909190919091505560018360010180549050610be091906145be565b60105f878785818110610bf657610bf56145f1565b5b9050602002013581526020019081526020015f208190555033600d5f878785818110610c2557610c246145f1565b5b9050602002013581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508080600101915050610aac565b508060095f806004811115610c9b57610c9a6144d6565b5b6004811115610cad57610cac6144d6565b5b81526020019081526020015f205f828254610cc89190614653565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f684aec4c92b52f473a97bed4ba4b04707b216b94099c51e5170c71d31ff569ea5f8686604051610d1993929190614734565b60405180910390a250505050565b606060038054610d3690614791565b80601f0160208091040260200160405190810160405280929190818152602001828054610d6290614791565b8015610dad5780601f10610d8457610100808354040283529160200191610dad565b820191905f5260205f20905b815481529060010190602001808311610d9057829003601f168201915b5050505050905090565b5f80610dc1612475565b9050610dce81858561247c565b600191505092915050565b600f602052805f5260405f205f915090505481565b610df78261248e565b5f8111610e39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e309061480b565b60405180910390fd5b8060085f846004811115610e5057610e4f6144d6565b5b6004811115610e6257610e616144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01541015610eee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee590614899565b60405180910390fd5b610ef7826123d2565b8060085f846004811115610f0e57610f0d6144d6565b5b6004811115610f2057610f1f6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f828254610f7891906145be565b92505081905550610ffe3382600b5f866004811115610f9a57610f996144d6565b5b6004811115610fac57610fab6144d6565b5b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125849092919063ffffffff16565b8060095f846004811115611015576110146144d6565b5b6004811115611027576110266144d6565b5b81526020019081526020015f205f82825461104291906145be565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f83637d0d125e3dae88720b1ad229ce05c339c065b6282caf315dcb35a999d6d483836040516110919291906148b7565b60405180910390a25050565b5f63150b7a0260e01b9050949350505050565b5f600254905090565b6110c25f612603565b565b60605f8060085f8060048111156110de576110dd6144d6565b5b60048111156110f0576110ef6144d6565b5b81526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060800160405290815f82015481526020016001820180548060200260200160405190810160405280929190818152602001828054801561119957602002820191905f5260205f20905b815481526020019060010190808311611185575b505050505081526020016002820154815260200160038201548152505090505f816020015151146111e2576111ce5f85612797565b81606001516111dd9190614653565b6111e8565b80606001515b91508060200151925050915091565b5f80611201612475565b905061120e8582856129ea565b611219858585612a7c565b60019150509392505050565b6112a18160085f84600481111561123f5761123e6144d6565b5b6004811115611251576112506144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0154610dee565b6112aa816112ba565b50565b601481565b637c9d3d3081565b6112c38161248e565b6112cc81612603565b50565b5f6012905090565b6a115eec47f6cf7e3500000081565b5f6112ef612b6c565b905090565b636d90fe3081565b60a081565b61131261130c612475565b82612c22565b50565b6113dd60085f80600481111561132e5761132d6144d6565b5b60048111156113405761133f6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206001018054806020026020016040519081016040528092919081815260200182805480156113d357602002820191905f5260205f20905b8154815260200190600101908083116113bf575b505050505061180c565b6113e56110b9565b565b602881565b600e81815481106113fb575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6114758261248e565b600c5f83600481111561148b5761148a6144d6565b5b600481111561149d5761149c6144d6565b5b81526020019081526020015f20548110156114ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e49061494e565b60405180910390fd5b5f60085f846004811115611504576115036144d6565b5b6004811115611516576115156144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01540361165a574260085f84600481111561157d5761157c6144d6565b5b600481111561158f5761158e6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600201819055508060085f8460048111156115f5576115f46144d6565b5b6004811115611607576116066144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01819055506116ec565b611663826123d2565b8060085f84600481111561167a576116796144d6565b5b600481111561168c5761168b6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282546116e49190614653565b925050819055505b61176d333083600b5f876004811115611708576117076144d6565b5b600481111561171a576117196144d6565b5b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ca1909392919063ffffffff16565b8060095f846004811115611784576117836144d6565b5b6004811115611796576117956144d6565b5b81526020019081526020015f205f8282546117b19190614653565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167f3cf14181ae25669a913d72411736fc5c01f538fa503e963b0b2e56bcefb3edaf83836040516118009291906148b7565b60405180910390a25050565b5f81510361184f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611846906149b6565b60405180910390fd5b5f60085f806004811115611866576118656144d6565b5b6004811115611878576118776144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f81600101805490501161190b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190290614a1e565b60405180910390fd5b6119145f6123d2565b5f825190505f5b81811015611bf9573373ffffffffffffffffffffffffffffffffffffffff16600d5f8684815181106119505761194f6145f1565b5b602002602001015181526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d290614a86565b60405180910390fd5b5f60105f8684815181106119f2576119f16145f1565b5b602002602001015181526020019081526020015f205490505f60018560010180549050611a1f91906145be565b9050808214611a9e57846001018181548110611a3e57611a3d6145f1565b5b905f5260205f200154856001018381548110611a5d57611a5c6145f1565b5b905f5260205f2001819055508160105f876001018581548110611a8357611a826145f1565b5b905f5260205f20015481526020019081526020015f20819055505b84600101805480611ab257611ab1614aa4565b5b600190038181905f5260205f20015f90559055600d5f878581518110611adb57611ada6145f1565b5b602002602001015181526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600b5f806004811115611b2857611b276144d6565b5b6004811115611b3a57611b396144d6565b5b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3033898781518110611b9757611b966145f1565b5b60200260200101516040518463ffffffff1660e01b8152600401611bbd9392919061461e565b5f604051808303815f87803b158015611bd4575f80fd5b505af1158015611be6573d5f803e3d5ffd5b505050508280600101935050505061191b565b508060095f806004811115611c1157611c106144d6565b5b6004811115611c2357611c226144d6565b5b81526020019081526020015f205f828254611c3e91906145be565b925050819055505f826001018054905003611e0a575f600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f6001600e80549050611ca791906145be565b9050808214611dc357600e8181548110611cc457611cc36145f1565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600e8381548110611d0057611cff6145f1565b5b905f5260205f20015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600f5f600e8581548110611d5d57611d5c6145f1565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b600e805480611dd557611dd4614aa4565b5b600190038181905f5260205f20015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055905550505b3373ffffffffffffffffffffffffffffffffffffffff167f26d429555a03b06a860d74ebe69930a09a0b7f4d37eca0ea63d37385b3d015e65f85604051611e52929190614ad1565b60405180910390a2505050565b611e7182611e6b612475565b836129ea565b611e7b8282612c22565b5050565b600d602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f611eb982612d23565b9050919050565b6375171db081565b5f6060805f805f6060611ed9612d69565b611ee1612da4565b46305f801b5f67ffffffffffffffff811115611f0057611eff613d3b565b5b604051908082528060200260200182016040528015611f2e5781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b6009602052805f5260405f205f915090505481565b606060048054611f9190614791565b80601f0160208091040260200160405190810160405280929190818152602001828054611fbd90614791565b80156120085780601f10611fdf57610100808354040283529160200191612008565b820191905f5260205f20905b815481529060010190602001808311611feb57829003601f168201915b5050505050905090565b6010602052805f5260405f205f915090505481565b5f80612031612475565b905061203e818585612a7c565b600191505092915050565b6384235cb081565b600a81565b6008602052815f5260405f20602052805f5260405f205f9150915050805f0154908060020154908060030154905083565b605081565b600a602052805f5260405f205f915090505481565b834211156120e657836040517f627913020000000000000000000000000000000000000000000000000000000081526004016120dd9190613cbd565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886121148c612ddf565b8960405160200161212a96959493929190614aff565b6040516020818303038152906040528051906020012090505f61214c82612e32565b90505f61215b82878787612e4b565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146121cf57808a6040517f4b800e460000000000000000000000000000000000000000000000000000000081526004016121c6929190614b5e565b60405180910390fd5b6121da8a8a8a61247c565b50505050505050505050565b5f806121f18461248e565b5f60085f866004811115612208576122076144d6565b5b600481111561221a576122196144d6565b5b81526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060800160405290815f8201548152602001600182018054806020026020016040519081016040528092919081815260200182805480156122c357602002820191905f5260205f20905b8154815260200190600101908083116122af575b505050505081526020016002820154815260200160038201548152505090506122ec8585612797565b81606001516122fb9190614653565b9150805f01519250509250929050565b600c602052805f5260405f205f915090505481565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b600b602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60085f8360048111156123e9576123e86144d6565b5b60048111156123fb576123fa6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20905061244f8233612797565b816003015f8282546124619190614653565b925050819055504281600201819055505050565b5f33905090565b6124898383836001612e79565b505050565b600260048111156124a2576124a16144d6565b5b8160048111156124b5576124b46144d6565b5b14806124e55750600160048111156124d0576124cf6144d6565b5b8160048111156124e3576124e26144d6565b5b145b806125145750600360048111156124ff576124fe6144d6565b5b816004811115612512576125116144d6565b5b145b80612542575060048081111561252d5761252c6144d6565b5b8160048111156125405761253f6144d6565b5b145b612581576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257890614bf5565b60405180910390fd5b50565b6125fe838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016125b7929190614c13565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613048565b505050565b5f60085f83600481111561261a576126196144d6565b5b600481111561262c5761262b6144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600301546126828333612797565b61268c9190614653565b90505f81116126d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126c790614c84565b60405180910390fd5b6a115eec47f6cf7e35000000816126e56110b0565b6126ef9190614653565b1115612730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161272790614cec565b60405180910390fd5b612739826130dd565b6127433382613166565b3373ffffffffffffffffffffffffffffffffffffffff167f721da0e761006d69a1240bd9ca78df4c4cb651e29fde11b2702993c175eadd5a838360405161278b9291906148b7565b60405180910390a25050565b5f8060085f8560048111156127af576127ae6144d6565b5b60048111156127c1576127c06144d6565b5b81526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060800160405290815f82015481526020016001820180548060200260200160405190810160405280929190818152602001828054801561286a57602002820191905f5260205f20905b815481526020019060010190808311612856575b505050505081526020016002820154815260200160038201548152505090505f636d90fe3042101561289f5760a090506128e6565b6375171db04210156128b457605090506128e5565b637c9d3d304210156128c957602890506128e4565b6384235cb04210156128de57601490506128e3565b600a90505b5b5b5b5f8060048111156128fa576128f96144d6565b5b86600481111561290d5761290c6144d6565b5b0361291d57826020015151612922565b825f01515b90505f806004811115612938576129376144d6565b5b87600481111561294b5761294a6144d6565b5b03612957576001612961565b670de0b6b3a76400005b67ffffffffffffffff16905080600a5f896004811115612984576129836144d6565b5b6004811115612996576129956144d6565b5b81526020019081526020015f205484848760400151426129b691906145be565b6129c09190614d0a565b6129ca9190614d0a565b6129d49190614d0a565b6129de9190614d78565b94505050505092915050565b5f6129f58484612320565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612a765781811015612a67578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401612a5e93929190614da8565b60405180910390fd5b612a7584848484035f612e79565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612aec575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401612ae39190614131565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612b5c575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401612b539190614131565b60405180910390fd5b612b678383836131e5565b505050565b5f7f00000000000000000000000088266f9eb705f5282a2507a9c418821a2ac9f8bd73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015612be757507f000000000000000000000000000000000000000000000000000000000000a4b146145b15612c14577f4741babb4220cbd0d4757f8db052a72ace57548d0c29bbcf0dd38bc826099ade9050612c1f565b612c1c6133fe565b90505b90565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612c92575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401612c899190614131565b60405180910390fd5b612c9d825f836131e5565b5050565b612d1d848573ffffffffffffffffffffffffffffffffffffffff166323b872dd868686604051602401612cd69392919061461e565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613048565b50505050565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6060612d9f60057f4e7574636173680000000000000000000000000000000000000000000000000761349390919063ffffffff16565b905090565b6060612dda60067f310000000000000000000000000000000000000000000000000000000000000161349390919063ffffffff16565b905090565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f612e44612e3e612b6c565b83613540565b9050919050565b5f805f80612e5b88888888613580565b925092509250612e6b8282613667565b829350505050949350505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612ee9575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401612ee09190614131565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612f59575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401612f509190614131565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015613042578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516130399190613cbd565b60405180910390a35b50505050565b5f613072828473ffffffffffffffffffffffffffffffffffffffff166137c990919063ffffffff16565b90505f8151141580156130965750808060200190518101906130949190614e07565b155b156130d857826040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016130cf9190614131565b60405180910390fd5b505050565b5f60085f8360048111156130f4576130f36144d6565b5b6004811115613106576131056144d6565b5b81526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f81600301819055504281600201819055505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036131d6575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016131cd9190614131565b60405180910390fd5b6131e15f83836131e5565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613235578060025f8282546132299190614653565b92505081905550613303565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156132be578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016132b593929190614da8565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361334a578060025f8282540392505081905550613394565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516133f19190613cbd565b60405180910390a3505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f6178d1fae8eec4bf0fefca4e486ad0507eec9e7c3d41671a180cdc3025a5d68b7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001613478959493929190614e32565b60405160208183030381529060405280519060200120905090565b606060ff5f1b83146134af576134a8836137de565b905061353a565b8180546134bb90614791565b80601f01602080910402602001604051908101604052809291908181526020018280546134e790614791565b80156135325780601f1061350957610100808354040283529160200191613532565b820191905f5260205f20905b81548152906001019060200180831161351557829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c11156135bc575f60038592509250925061365d565b5f6001888888886040515f81526020016040526040516135df9493929190614e83565b6020604051602081039080840390855afa1580156135ff573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613650575f60015f801b9350935093505061365d565b805f805f1b935093509350505b9450945094915050565b5f600381111561367a576136796144d6565b5b82600381111561368d5761368c6144d6565b5b03156137c557600160038111156136a7576136a66144d6565b5b8260038111156136ba576136b96144d6565b5b036136f1576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115613705576137046144d6565b5b826003811115613718576137176144d6565b5b0361375c57805f1c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016137539190613cbd565b60405180910390fd5b60038081111561376f5761376e6144d6565b5b826003811115613782576137816144d6565b5b036137c457806040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004016137bb91906140de565b60405180910390fd5b5b5050565b60606137d683835f613850565b905092915050565b60605f6137ea83613919565b90505f602067ffffffffffffffff81111561380857613807613d3b565b5b6040519080825280601f01601f19166020018201604052801561383a5781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b60608147101561389757306040517fcd78605900000000000000000000000000000000000000000000000000000000815260040161388e9190614131565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff1684866040516138bf9190614f0a565b5f6040518083038185875af1925050503d805f81146138f9576040519150601f19603f3d011682016040523d82523d5f602084013e6138fe565b606091505b509150915061390e868383613967565b925050509392505050565b5f8060ff835f1c169050601f81111561395e576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b60608261397c57613977826139f4565b6139ec565b5f82511480156139a257505f8473ffffffffffffffffffffffffffffffffffffffff163b145b156139e457836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016139db9190614131565b60405180910390fd5b8190506139ed565b5b9392505050565b5f81511115613a065780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112613a6a57613a69613a49565b5b8235905067ffffffffffffffff811115613a8757613a86613a4d565b5b602083019150836020820283011115613aa357613aa2613a51565b5b9250929050565b5f8060208385031215613ac057613abf613a41565b5b5f83013567ffffffffffffffff811115613add57613adc613a45565b5b613ae985828601613a55565b92509250509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613b3782613af5565b613b418185613aff565b9350613b51818560208601613b0f565b613b5a81613b1d565b840191505092915050565b5f6020820190508181035f830152613b7d8184613b2d565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613bae82613b85565b9050919050565b613bbe81613ba4565b8114613bc8575f80fd5b50565b5f81359050613bd981613bb5565b92915050565b5f819050919050565b613bf181613bdf565b8114613bfb575f80fd5b50565b5f81359050613c0c81613be8565b92915050565b5f8060408385031215613c2857613c27613a41565b5b5f613c3585828601613bcb565b9250506020613c4685828601613bfe565b9150509250929050565b5f8115159050919050565b613c6481613c50565b82525050565b5f602082019050613c7d5f830184613c5b565b92915050565b5f60208284031215613c9857613c97613a41565b5b5f613ca584828501613bcb565b91505092915050565b613cb781613bdf565b82525050565b5f602082019050613cd05f830184613cae565b92915050565b60058110613ce2575f80fd5b50565b5f81359050613cf381613cd6565b92915050565b5f8060408385031215613d0f57613d0e613a41565b5b5f613d1c85828601613ce5565b9250506020613d2d85828601613bfe565b9150509250929050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613d7182613b1d565b810181811067ffffffffffffffff82111715613d9057613d8f613d3b565b5b80604052505050565b5f613da2613a38565b9050613dae8282613d68565b919050565b5f67ffffffffffffffff821115613dcd57613dcc613d3b565b5b613dd682613b1d565b9050602081019050919050565b828183375f83830152505050565b5f613e03613dfe84613db3565b613d99565b905082815260208101848484011115613e1f57613e1e613d37565b5b613e2a848285613de3565b509392505050565b5f82601f830112613e4657613e45613a49565b5b8135613e56848260208601613df1565b91505092915050565b5f805f8060808587031215613e7757613e76613a41565b5b5f613e8487828801613bcb565b9450506020613e9587828801613bcb565b9350506040613ea687828801613bfe565b925050606085013567ffffffffffffffff811115613ec757613ec6613a45565b5b613ed387828801613e32565b91505092959194509250565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613f1381613edf565b82525050565b5f602082019050613f2c5f830184613f0a565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613f6481613bdf565b82525050565b5f613f758383613f5b565b60208301905092915050565b5f602082019050919050565b5f613f9782613f32565b613fa18185613f3c565b9350613fac83613f4c565b805f5b83811015613fdc578151613fc38882613f6a565b9750613fce83613f81565b925050600181019050613faf565b5085935050505092915050565b5f6040820190508181035f8301526140018185613f8d565b90506140106020830184613cae565b9392505050565b5f805f6060848603121561402e5761402d613a41565b5b5f61403b86828701613bcb565b935050602061404c86828701613bcb565b925050604061405d86828701613bfe565b9150509250925092565b5f6020828403121561407c5761407b613a41565b5b5f61408984828501613ce5565b91505092915050565b5f60ff82169050919050565b6140a781614092565b82525050565b5f6020820190506140c05f83018461409e565b92915050565b5f819050919050565b6140d8816140c6565b82525050565b5f6020820190506140f15f8301846140cf565b92915050565b5f6020828403121561410c5761410b613a41565b5b5f61411984828501613bfe565b91505092915050565b61412b81613ba4565b82525050565b5f6020820190506141445f830184614122565b92915050565b5f67ffffffffffffffff82111561416457614163613d3b565b5b602082029050602081019050919050565b5f6141876141828461414a565b613d99565b905080838252602082019050602084028301858111156141aa576141a9613a51565b5b835b818110156141d357806141bf8882613bfe565b8452602084019350506020810190506141ac565b5050509392505050565b5f82601f8301126141f1576141f0613a49565b5b8135614201848260208601614175565b91505092915050565b5f6020828403121561421f5761421e613a41565b5b5f82013567ffffffffffffffff81111561423c5761423b613a45565b5b614248848285016141dd565b91505092915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b61428581614251565b82525050565b5f60e08201905061429e5f83018a61427c565b81810360208301526142b08189613b2d565b905081810360408301526142c48188613b2d565b90506142d36060830187613cae565b6142e06080830186614122565b6142ed60a08301856140cf565b81810360c08301526142ff8184613f8d565b905098975050505050505050565b5f806040838503121561432357614322613a41565b5b5f61433085828601613ce5565b925050602061434185828601613bcb565b9150509250929050565b5f60608201905061435e5f830186613cae565b61436b6020830185613cae565b6143786040830184613cae565b949350505050565b61438981614092565b8114614393575f80fd5b50565b5f813590506143a481614380565b92915050565b6143b3816140c6565b81146143bd575f80fd5b50565b5f813590506143ce816143aa565b92915050565b5f805f805f805f60e0888a0312156143ef576143ee613a41565b5b5f6143fc8a828b01613bcb565b975050602061440d8a828b01613bcb565b965050604061441e8a828b01613bfe565b955050606061442f8a828b01613bfe565b94505060806144408a828b01614396565b93505060a06144518a828b016143c0565b92505060c06144628a828b016143c0565b91505092959891949750929550565b5f6040820190506144845f830185613cae565b6144916020830184613cae565b9392505050565b5f80604083850312156144ae576144ad613a41565b5b5f6144bb85828601613bcb565b92505060206144cc85828601613bcb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b7f546f6b656e206e756d626572206d75737420626520686967686572207468616e5f8201527f206d696e696d696d756d206465706f7369740000000000000000000000000000602082015250565b5f61455d603283613aff565b915061456882614503565b604082019050919050565b5f6020820190508181035f83015261458a81614551565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6145c882613bdf565b91506145d383613bdf565b92508282039050818111156145eb576145ea614591565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6060820190506146315f830186614122565b61463e6020830185614122565b61464b6040830184613cae565b949350505050565b5f61465d82613bdf565b915061466883613bdf565b92508282019050808211156146805761467f614591565b5b92915050565b60058110614697576146966144d6565b5b50565b5f8190506146a782614686565b919050565b5f6146b68261469a565b9050919050565b6146c6816146ac565b82525050565b5f80fd5b82818337505050565b5f6146e48385613f3c565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115614717576147166146cc565b5b6020830292506147288385846146d0565b82840190509392505050565b5f6040820190506147475f8301866146bd565b818103602083015261475a8184866146d9565b9050949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806147a857607f821691505b6020821081036147bb576147ba614764565b5b50919050565b7f416d6f756e74206d7573742062652067726561746572207468616e207a65726f5f82015250565b5f6147f5602083613aff565b9150614800826147c1565b602082019050919050565b5f6020820190508181035f830152614822816147e9565b9050919050565b7f43616e2774207769746864726177206d6f7265207468616e20796f75206861765f8201527f65207374616b6564000000000000000000000000000000000000000000000000602082015250565b5f614883602883613aff565b915061488e82614829565b604082019050919050565b5f6020820190508181035f8301526148b081614877565b9050919050565b5f6040820190506148ca5f8301856146bd565b6148d76020830184613cae565b9392505050565b7f416d6f756e74206d75737420626520686967686572207468616e206d696e696d5f8201527f696d756d206465706f7369740000000000000000000000000000000000000000602082015250565b5f614938602c83613aff565b9150614943826148de565b604082019050919050565b5f6020820190508181035f8301526149658161492c565b9050919050565b7f4e6f20746f6b656e4964732070726f76696465640000000000000000000000005f82015250565b5f6149a0601483613aff565b91506149ab8261496c565b602082019050919050565b5f6020820190508181035f8301526149cd81614994565b9050919050565b7f4e6f20746f6b656e73207374616b656420746f207769746864726177000000005f82015250565b5f614a08601c83613aff565b9150614a13826149d4565b602082019050919050565b5f6020820190508181035f830152614a35816149fc565b9050919050565b7f4e6f7420746865207374616b6572206f662074686520746f6b656e00000000005f82015250565b5f614a70601b83613aff565b9150614a7b82614a3c565b602082019050919050565b5f6020820190508181035f830152614a9d81614a64565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f604082019050614ae45f8301856146bd565b8181036020830152614af68184613f8d565b90509392505050565b5f60c082019050614b125f8301896140cf565b614b1f6020830188614122565b614b2c6040830187614122565b614b396060830186613cae565b614b466080830185613cae565b614b5360a0830184613cae565b979650505050505050565b5f604082019050614b715f830185614122565b614b7e6020830184614122565b9392505050565b7f496e76616c6964204552433230207374616b656420746f6b656e2073796d626f5f8201527f6c00000000000000000000000000000000000000000000000000000000000000602082015250565b5f614bdf602183613aff565b9150614bea82614b85565b604082019050919050565b5f6020820190508181035f830152614c0c81614bd3565b9050919050565b5f604082019050614c265f830185614122565b614c336020830184613cae565b9392505050565b7f4e6f207265776172647320746f20636c61696d000000000000000000000000005f82015250565b5f614c6e601383613aff565b9150614c7982614c3a565b602082019050919050565b5f6020820190508181035f830152614c9b81614c62565b9050919050565b7f45786365656473204d41585f535550504c5900000000000000000000000000005f82015250565b5f614cd6601283613aff565b9150614ce182614ca2565b602082019050919050565b5f6020820190508181035f830152614d0381614cca565b9050919050565b5f614d1482613bdf565b9150614d1f83613bdf565b9250828202614d2d81613bdf565b91508282048414831517614d4457614d43614591565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614d8282613bdf565b9150614d8d83613bdf565b925082614d9d57614d9c614d4b565b5b828204905092915050565b5f606082019050614dbb5f830186614122565b614dc86020830185613cae565b614dd56040830184613cae565b949350505050565b614de681613c50565b8114614df0575f80fd5b50565b5f81519050614e0181614ddd565b92915050565b5f60208284031215614e1c57614e1b613a41565b5b5f614e2984828501614df3565b91505092915050565b5f60a082019050614e455f8301886140cf565b614e5260208301876140cf565b614e5f60408301866140cf565b614e6c6060830185613cae565b614e796080830184614122565b9695505050505050565b5f608082019050614e965f8301876140cf565b614ea3602083018661409e565b614eb060408301856140cf565b614ebd60608301846140cf565b95945050505050565b5f81519050919050565b5f81905092915050565b5f614ee482614ec6565b614eee8185614ed0565b9350614efe818560208601613b0f565b80840191505092915050565b5f614f158284614eda565b91508190509291505056fea2646970667358221220ac2268774346f622e49c4b552a07268603e4669d074afd830f259c3c471245b364736f6c63430008190033

Deployed Bytecode Sourcemap

103887:14683:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110292:1275;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;68642:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;70960:215;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;106045:57;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117120:586;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;102946:198;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;69744:99;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;114275:80;;;:::i;:::-;;114830:491;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;71753:283;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117841:160;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;104766:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104362:56;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117714:119;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;69595:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104048:63;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80913:114;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104236:56;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104597:50;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;81629:89;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;115453:145;;;:::i;:::-;;104710:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105961:33;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;69906:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116240:795;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111730:1908;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;82047:161;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;105847:52;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80639:161;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104299:56;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41246:580;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;105604:51;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68852:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;106190:58;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;70229:182;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104425:56;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104822:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105469:60;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;104654:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105697:46;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79744:836;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;118151:416;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;105796:42;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;70474:167;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105750:39;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110292:1275;110403:8;:21;110412:11;110403:21;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;110383:9;;:16;;:41;;110361:141;;;;;;;;;;;;:::i;:::-;;;;;;;;;110515:21;110539:7;:20;110547:11;110539:20;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:32;110560:10;110539:32;;;;;;;;;;;;;;;110515:56;;110619:1;110588:6;:21;;:28;;;;:32;110584:302;;;110637:36;110661:11;110637:23;:36::i;:::-;110584:302;;;110706:16;110728:10;110706:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110817:1;110791:16;:23;;;;:27;;;;:::i;:::-;110754:22;:34;110777:10;110754:34;;;;;;;;;;;;;;;:64;;;;110859:15;110833:6;:23;;:41;;;;110584:302;110898:14;110915:9;;:16;;110898:33;;110947:9;110942:507;110962:6;110958:1;:10;110942:507;;;110995:5;:18;111001:11;110995:18;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;110987:44;;;111050:10;111087:4;111111:9;;111121:1;111111:12;;;;;;;:::i;:::-;;;;;;;;110987:151;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111155:6;:21;;111182:9;;111192:1;111182:12;;;;;;;:::i;:::-;;;;;;;;111155:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111315:1;111267:6;:21;;:28;;;;:49;;;;:::i;:::-;111210:23;:37;111234:9;;111244:1;111234:12;;;;;;;:::i;:::-;;;;;;;;111210:37;;;;;;;;;;;:106;;;;111365:10;111331:17;:31;111349:9;;111359:1;111349:12;;;;;;;:::i;:::-;;;;;;;;111331:31;;;;;;;;;;;;:44;;;;;;;;;;;;;;;;;;111419:3;;;;;;;110942:507;;;;111493:6;111459:17;:30;111477:11;111459:30;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:40;;;;;;;:::i;:::-;;;;;;;;111524:10;111517:42;;;111536:11;111549:9;;111517:42;;;;;;;;:::i;:::-;;;;;;;;110350:1217;;110292:1275;;:::o;68642:91::-;68687:13;68720:5;68713:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68642:91;:::o;70960:215::-;71058:4;71075:13;71091:12;:10;:12::i;:::-;71075:28;;71114:31;71123:5;71130:7;71139:5;71114:8;:31::i;:::-;71163:4;71156:11;;;70960:215;;;;:::o;106045:57::-;;;;;;;;;;;;;;;;;:::o;117120:586::-;117193:19;117205:6;117193:11;:19::i;:::-;117243:1;117233:7;:11;117225:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;117354:7;117316;:15;117324:6;117316:15;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:27;117332:10;117316:27;;;;;;;;;;;;;;;:34;;;:45;;117294:135;;;;;;;;;;;;:::i;:::-;;;;;;;;;117442:31;117466:6;117442:23;:31::i;:::-;117522:7;117484;:15;117492:6;117484:15;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:27;117500:10;117484:27;;;;;;;;;;;;;;;:34;;;:45;;;;;;;:::i;:::-;;;;;;;;117542:55;117577:10;117589:7;117549:5;:13;117555:6;117549:13;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;117542:34;;;;:55;;;;;:::i;:::-;117637:7;117608:17;:25;117626:6;117608:25;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:36;;;;;;;:::i;:::-;;;;;;;;117670:10;117660:38;;;117682:6;117690:7;117660:38;;;;;;;:::i;:::-;;;;;;;;117120:586;;:::o;102946:198::-;103080:6;103106:30;;;103099:37;;102946:198;;;;;;:::o;69744:99::-;69796:7;69823:12;;69816:19;;69744:99;:::o;114275:80::-;114321:26;114335:11;114321:13;:26::i;:::-;114275:80::o;114830:491::-;114938:32;114972:25;115015:21;115039:7;:20;115047:11;115039:20;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:27;115060:5;115039:27;;;;;;;;;;;;;;;115015:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115130:1;115097:7;:22;;;:29;:34;:153;;115214:36;115231:11;115244:5;115214:16;:36::i;:::-;115187:7;:24;;;:63;;;;:::i;:::-;115097:153;;;115147:7;:24;;;115097:153;115077:173;;115271:7;:22;;;115263:50;;;114830:491;;;:::o;71753:283::-;71874:4;71891:15;71909:12;:10;:12::i;:::-;71891:30;;71932:37;71948:4;71954:7;71963:5;71932:15;:37::i;:::-;71980:26;71990:4;71996:2;72000:5;71980:9;:26::i;:::-;72024:4;72017:11;;;71753:283;;;;;:::o;117841:160::-;117900:57;117914:6;117922:7;:15;117930:6;117922:15;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:27;117938:10;117922:27;;;;;;;;;;;;;;;:34;;;117900:13;:57::i;:::-;117968:25;117986:6;117968:17;:25::i;:::-;117841:160;:::o;104766:49::-;104813:2;104766:49;:::o;104362:56::-;104408:10;104362:56;:::o;117714:119::-;117774:19;117786:6;117774:11;:19::i;:::-;117804:21;117818:6;117804:13;:21::i;:::-;117714:119;:::o;69595:84::-;69644:5;69669:2;69662:9;;69595:84;:::o;104048:63::-;104085:26;104048:63;:::o;80913:114::-;80972:7;80999:20;:18;:20::i;:::-;80992:27;;80913:114;:::o;104236:56::-;104282:10;104236:56;:::o;104597:50::-;104644:3;104597:50;:::o;81629:89::-;81684:26;81690:12;:10;:12::i;:::-;81704:5;81684;:26::i;:::-;81629:89;:::o;115453:145::-;115500:61;115513:7;:20;115521:11;115513:20;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:32;115534:10;115513:32;;;;;;;;;;;;;;;:47;;115500:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:12;:61::i;:::-;115572:18;:16;:18::i;:::-;115453:145::o;104710:49::-;104757:2;104710:49;:::o;105961:33::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;69906:118::-;69971:7;69998:9;:18;70008:7;69998:18;;;;;;;;;;;;;;;;69991:25;;69906:118;;;:::o;116240:795::-;116312:19;116324:6;116312:11;:19::i;:::-;116377:8;:16;116386:6;116377:16;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;116366:7;:27;;116344:121;;;;;;;;;;;;:::i;:::-;;;;;;;;;116520:1;116482:7;:15;116490:6;116482:15;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:27;116498:10;116482:27;;;;;;;;;;;;;;;:34;;;:39;116478:317;;116585:15;116538:7;:15;116546:6;116538:15;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:27;116554:10;116538:27;;;;;;;;;;;;;;;:44;;:62;;;;116652:7;116615;:15;116623:6;116615:15;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:27;116631:10;116615:27;;;;;;;;;;;;;;;:34;;:44;;;;116478:317;;;116692:31;116716:6;116692:23;:31::i;:::-;116776:7;116738;:15;116746:6;116738:15;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:27;116754:10;116738:27;;;;;;;;;;;;;;;:34;;;:45;;;;;;;:::i;:::-;;;;;;;;116478:317;116805:124;116858:10;116891:4;116911:7;116812:5;:13;116818:6;116812:13;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;116805:38;;;;:124;;;;;;:::i;:::-;116969:7;116940:17;:25;116958:6;116940:25;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:36;;;;;;;:::i;:::-;;;;;;;;116999:10;116992:35;;;117011:6;117019:7;116992:35;;;;;;;:::i;:::-;;;;;;;;116240:795;;:::o;111730:1908::-;111826:1;111806:9;:16;:21;111798:54;;;;;;;;;;;;:::i;:::-;;;;;;;;;111865:21;111889:7;:20;111897:11;111889:20;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:32;111910:10;111889:32;;;;;;;;;;;;;;;111865:56;;111985:1;111954:6;:21;;:28;;;;:32;111932:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;112053:36;112077:11;112053:23;:36::i;:::-;112102:14;112119:9;:16;112102:33;;112151:9;112146:928;112166:6;112162:1;:10;112146:928;;;112252:10;112217:45;;:17;:31;112235:9;112245:1;112235:12;;;;;;;;:::i;:::-;;;;;;;;112217:31;;;;;;;;;;;;;;;;;;;;;:45;;;112191:134;;;;;;;;;;;;:::i;:::-;;;;;;;;;112342:13;112358:23;:37;112382:9;112392:1;112382:12;;;;;;;;:::i;:::-;;;;;;;;112358:37;;;;;;;;;;;;112342:53;;112410:22;112466:1;112435:6;:21;;:28;;;;:32;;;;:::i;:::-;112410:57;;112495:14;112486:5;:23;112482:252;;112561:6;:21;;112605:14;112561:77;;;;;;;;:::i;:::-;;;;;;;;;;112530:6;:21;;112552:5;112530:28;;;;;;;;:::i;:::-;;;;;;;;;:108;;;;112713:5;112657:23;:53;112681:6;:21;;112703:5;112681:28;;;;;;;;:::i;:::-;;;;;;;;;;112657:53;;;;;;;;;;;:61;;;;112482:252;112748:6;:21;;:27;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;112799:17;:31;112817:9;112827:1;112817:12;;;;;;;;:::i;:::-;;;;;;;;112799:31;;;;;;;;;;;;112792:38;;;;;;;;;;;112855:5;:18;112861:11;112855:18;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;112847:44;;;112918:4;112942:10;112971:9;112981:1;112971:12;;;;;;;;:::i;:::-;;;;;;;;112847:151;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113044:3;;;;;;;112176:898;;112146:928;;;;113118:6;113084:17;:30;113102:11;113084:30;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:40;;;;;;;:::i;:::-;;;;;;;;113173:1;113141:6;:21;;:28;;;;:33;113137:433;;113191:13;113207:22;:34;113230:10;113207:34;;;;;;;;;;;;;;;;113191:50;;113256:23;113308:1;113282:16;:23;;;;:27;;;;:::i;:::-;113256:53;;113337:15;113328:5;:24;113324:198;;113399:16;113416:15;113399:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;113373:16;113390:5;113373:23;;;;;;;;:::i;:::-;;;;;;;;;;:59;;;;;;;;;;;;;;;;;;113501:5;113451:22;:47;113474:16;113491:5;113474:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;113451:47;;;;;;;;;;;;;;;:55;;;;113324:198;113536:16;:22;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;113176:394;;113137:433;113595:10;113585:45;;;113607:11;113620:9;113585:45;;;;;;;:::i;:::-;;;;;;;;111787:1851;;111730:1908;:::o;82047:161::-;82123:45;82139:7;82148:12;:10;:12::i;:::-;82162:5;82123:15;:45::i;:::-;82179:21;82185:7;82194:5;82179;:21::i;:::-;82047:161;;:::o;105847:52::-;;;;;;;;;;;;;;;;;;;;;;:::o;80639:161::-;80746:7;80773:19;80786:5;80773:12;:19::i;:::-;80766:26;;80639:161;;;:::o;104299:56::-;104345:10;104299:56;:::o;41246:580::-;41349:13;41377:18;41410:21;41446:15;41476:25;41516:12;41543:27;41651:13;:11;:13::i;:::-;41679:16;:14;:16::i;:::-;41710:13;41746:4;41774:1;41766:10;;41805:1;41791:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41598:220;;;;;;;;;;;;;;;;;;;;;41246:580;;;;;;;:::o;105604:51::-;;;;;;;;;;;;;;;;;:::o;68852:95::-;68899:13;68932:7;68925:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68852:95;:::o;106190:58::-;;;;;;;;;;;;;;;;;:::o;70229:182::-;70298:4;70315:13;70331:12;:10;:12::i;:::-;70315:28;;70354:27;70364:5;70371:2;70375:5;70354:9;:27::i;:::-;70399:4;70392:11;;;70229:182;;;;:::o;104425:56::-;104471:10;104425:56;:::o;104822:49::-;104869:2;104822:49;:::o;105469:60::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;104654:49::-;104701:2;104654:49;:::o;105697:46::-;;;;;;;;;;;;;;;;;:::o;79744:836::-;79974:8;79956:15;:26;79952:99;;;80030:8;80006:33;;;;;;;;;;;:::i;:::-;;;;;;;;79952:99;80063:18;79040:119;80171:5;80195:7;80221:5;80245:16;80255:5;80245:9;:16::i;:::-;80280:8;80108:195;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;80084:230;;;;;;80063:251;;80327:12;80342:28;80359:10;80342:16;:28::i;:::-;80327:43;;80383:14;80400:28;80414:4;80420:1;80423;80426;80400:13;:28::i;:::-;80383:45;;80453:5;80443:15;;:6;:15;;;80439:90;;80503:6;80511:5;80482:35;;;;;;;;;;;;:::i;:::-;;;;;;;;80439:90;80541:31;80550:5;80557:7;80566:5;80541:8;:31::i;:::-;79941:639;;;79744:836;;;;;;;:::o;118151:416::-;118257:14;118273:25;118311:19;118323:6;118311:11;:19::i;:::-;118343:21;118367:7;:15;118375:6;118367:15;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:22;118383:5;118367:22;;;;;;;;;;;;;;;118343:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;118473:31;118490:6;118498:5;118473:16;:31::i;:::-;118433:7;:24;;;:71;;;;:::i;:::-;118400:104;;118525:7;:14;;;118517:42;;;118151:416;;;;;:::o;105796:42::-;;;;;;;;;;;;;;;;;:::o;70474:167::-;70579:7;70606:11;:18;70618:5;70606:18;;;;;;;;;;;;;;;:27;70625:7;70606:27;;;;;;;;;;;;;;;;70599:34;;70474:167;;;;:::o;105750:39::-;;;;;;;;;;;;;;;;;;;;;;:::o;109370:258::-;109439:21;109463:7;:16;109471:7;109463:16;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:28;109480:10;109463:28;;;;;;;;;;;;;;;109439:52;;109531:37;109548:7;109557:10;109531:16;:37::i;:::-;109504:6;:23;;;:64;;;;;;;:::i;:::-;;;;;;;;109605:15;109579:6;:23;;:41;;;;109428:200;109370:258;:::o;62666:98::-;62719:7;62746:10;62739:17;;62666:98;:::o;75846:130::-;75931:37;75940:5;75947:7;75956:5;75963:4;75931:8;:37::i;:::-;75846:130;;;:::o;115656:306::-;115751:10;115740:21;;;;;;;;:::i;:::-;;:7;:21;;;;;;;;:::i;:::-;;;:67;;;;115793:14;115782:25;;;;;;;;:::i;:::-;;:7;:25;;;;;;;;:::i;:::-;;;115740:67;:109;;;;115839:10;115828:21;;;;;;;;:::i;:::-;;:7;:21;;;;;;;;:::i;:::-;;;115740:109;:153;;;;115881:12;115870:23;;;;;;;;:::i;:::-;;:7;:23;;;;;;;;:::i;:::-;;;115740:153;115718:236;;;;;;;;;;;;:::i;:::-;;;;;;;;;115656:306;:::o;90080:162::-;90163:71;90183:5;90205;:14;;;90222:2;90226:5;90190:43;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90163:19;:71::i;:::-;90080:162;;;:::o;113766:501::-;113825:15;113896:7;:16;113904:7;113896:16;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:28;113913:10;113896:28;;;;;;;;;;;;;;;:45;;;113843:37;113860:7;113869:10;113843:16;:37::i;:::-;:98;;;;:::i;:::-;113825:116;;113970:1;113960:7;:11;113952:43;;;;;;;;;;;;:::i;:::-;;;;;;;;;104085:26;114030:7;114014:13;:11;:13::i;:::-;:23;;;;:::i;:::-;:37;;114006:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;114131:31;114154:7;114131:22;:31::i;:::-;114175:26;114181:10;114193:7;114175:5;:26::i;:::-;114230:10;114219:40;;;114242:7;114251;114219:40;;;;;;;:::i;:::-;;;;;;;;113814:453;113766:501;:::o;107928:1281::-;108035:16;108064:20;108087:7;:16;108095:7;108087:16;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:25;108104:7;108087:25;;;;;;;;;;;;;;;108064:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108208:24;104282:10;108247:15;:37;108243:526;;;104644:3;108301:39;;108243:526;;;104345:10;108362:15;:37;108358:411;;;104701:2;108416:39;;108358:411;;;104408:10;108477:15;:37;108473:296;;;104757:2;108531:39;;108473:296;;;104471:10;108592:15;:37;108588:181;;;104813:2;108646:39;;108588:181;;;104869:2;108718:39;;108588:181;108473:296;108358:411;108243:526;108781:19;108814:11;108803:22;;;;;;;;:::i;:::-;;:7;:22;;;;;;;;:::i;:::-;;;:95;;108870:6;:21;;;:28;108803:95;;;108841:6;:13;;;108803:95;108781:117;;108983:12;109009:11;108998:22;;;;;;;;:::i;:::-;;:7;:22;;;;;;;;:::i;:::-;;;:33;;109030:1;108998:33;;;109023:4;108998:33;108983:48;;;;109196:4;109171:12;:21;109184:7;109171:21;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;109139:16;109112:11;109072:6;:23;;;109054:15;:41;;;;:::i;:::-;109053:70;;;;:::i;:::-;:102;;;;:::i;:::-;:139;;;;:::i;:::-;109052:148;;;;:::i;:::-;109044:157;;;;;;107928:1281;;;;:::o;77605:603::-;77739:24;77766:25;77776:5;77783:7;77766:9;:25::i;:::-;77739:52;;77826:17;77806:16;:37;77802:399;;77883:5;77864:16;:24;77860:214;;;77965:7;77995:16;78034:5;77916:142;;;;;;;;;;;;;:::i;:::-;;;;;;;;77860:214;78117:57;78126:5;78133:7;78161:5;78142:16;:24;78168:5;78117:8;:57::i;:::-;77802:399;77728:480;77605:603;;;:::o;72421:308::-;72521:1;72505:18;;:4;:18;;;72501:88;;72574:1;72547:30;;;;;;;;;;;:::i;:::-;;;;;;;;72501:88;72617:1;72603:16;;:2;:16;;;72599:88;;72672:1;72643:32;;;;;;;;;;;:::i;:::-;;;;;;;;72599:88;72697:24;72705:4;72711:2;72715:5;72697:7;:24::i;:::-;72421:308;;;:::o;39715:268::-;39768:7;39809:11;39792:28;;39800:4;39792:28;;;:63;;;;;39841:14;39824:13;:31;39792:63;39788:188;;;39879:22;39872:29;;;;39788:188;39941:23;:21;:23::i;:::-;39934:30;;39715:268;;:::o;75082:211::-;75172:1;75153:21;;:7;:21;;;75149:91;;75225:1;75198:30;;;;;;;;;;;:::i;:::-;;;;;;;;75149:91;75250:35;75258:7;75275:1;75279:5;75250:7;:35::i;:::-;75082:211;;:::o;90487:270::-;90631:118;90665:5;90700;:18;;;90721:4;90727:2;90731:5;90685:53;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90631:19;:118::i;:::-;90487:270;;;;:::o;615:109::-;675:7;702;:14;710:5;702:14;;;;;;;;;;;;;;;;695:21;;615:109;;;:::o;42155:128::-;42201:13;42234:41;42261:13;42234:5;:26;;:41;;;;:::i;:::-;42227:48;;42155:128;:::o;42618:137::-;42667:13;42700:47;42730:16;42700:8;:29;;:47;;;;:::i;:::-;42693:54;;42618:137;:::o;845:402::-;905:7;1212;:14;1220:5;1212:14;;;;;;;;;;;;;;;;:16;;;;;;;;;;;;1205:23;;845:402;;;:::o;40983:207::-;41076:7;41116:66;41149:20;:18;:20::i;:::-;41171:10;41116:32;:66::i;:::-;41096:86;;40983:207;;;:::o;50121:370::-;50249:7;50270:17;50289:18;50309:16;50329:88;50354:4;50373:1;50389;50405;50329:10;:88::i;:::-;50269:148;;;;;;50428:28;50440:5;50447:8;50428:11;:28::i;:::-;50474:9;50467:16;;;;;50121:370;;;;;;:::o;76827:486::-;77000:1;76983:19;;:5;:19;;;76979:91;;77055:1;77026:32;;;;;;;;;;;:::i;:::-;;;;;;;;76979:91;77103:1;77084:21;;:7;:21;;;77080:92;;77157:1;77129:31;;;;;;;;;;;:::i;:::-;;;;;;;;77080:92;77212:5;77182:11;:18;77194:5;77182:18;;;;;;;;;;;;;;;:27;77201:7;77182:27;;;;;;;;;;;;;;;:35;;;;77232:9;77228:78;;;77279:7;77263:31;;77272:5;77263:31;;;77288:5;77263:31;;;;;;:::i;:::-;;;;;;;;77228:78;76827:486;;;;:::o;93241:638::-;93665:23;93691:33;93719:4;93699:5;93691:27;;;;:33;;;;:::i;:::-;93665:59;;93760:1;93739:10;:17;:22;;:57;;;;;93777:10;93766:30;;;;;;;;;;;;:::i;:::-;93765:31;93739:57;93735:137;;;93853:5;93820:40;;;;;;;;;;;:::i;:::-;;;;;;;;93735:137;93311:568;93241:638;;:::o;109816:220::-;109884:21;109908:7;:16;109916:7;109908:16;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:28;109925:10;109908:28;;;;;;;;;;;;;;;109884:52;;109975:1;109949:6;:23;;:27;;;;110013:15;109987:6;:23;;:41;;;;109873:163;109816:220;:::o;74541:213::-;74631:1;74612:21;;:7;:21;;;74608:93;;74686:1;74657:32;;;;;;;;;;;:::i;:::-;;;;;;;;74608:93;74711:35;74727:1;74731:7;74740:5;74711:7;:35::i;:::-;74541:213;;:::o;73053:1135::-;73159:1;73143:18;;:4;:18;;;73139:552;;73297:5;73281:12;;:21;;;;;;;:::i;:::-;;;;;;;;73139:552;;;73335:19;73357:9;:15;73367:4;73357:15;;;;;;;;;;;;;;;;73335:37;;73405:5;73391:11;:19;73387:117;;;73463:4;73469:11;73482:5;73438:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;73387:117;73659:5;73645:11;:19;73627:9;:15;73637:4;73627:15;;;;;;;;;;;;;;;:37;;;;73320:371;73139:552;73721:1;73707:16;;:2;:16;;;73703:435;;73889:5;73873:12;;:21;;;;;;;;;;;73703:435;;;74106:5;74089:9;:13;74099:2;74089:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;73703:435;74170:2;74155:25;;74164:4;74155:25;;;74174:5;74155:25;;;;;;:::i;:::-;;;;;;;;73053:1135;;;:::o;39991:350::-;40046:7;37883:119;40179:11;40213:14;40250:13;40294:4;40114:204;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;40086:247;;;;;;40066:267;;39991:350;:::o;10143:298::-;10262:13;8048:66;10321:17;;10311:5;10292:46;10288:146;;10362:15;10371:5;10362:8;:15::i;:::-;10355:22;;;;10288:146;10417:5;10410:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10143:298;;;;;:::o;35467:435::-;35585:14;35697:4;35691:11;35728:10;35723:3;35716:23;35776:15;35769:4;35764:3;35760:14;35753:39;35829:10;35822:4;35817:3;35813:14;35806:34;35879:4;35874:3;35864:20;35854:30;;35665:230;35467:435;;;;:::o;48389:1593::-;48520:7;48529:12;48543:7;49490:66;49472:1;49464:10;;:92;49446:203;;;49599:1;49603:30;49635:1;49583:54;;;;;;;;49446:203;49746:14;49763:24;49773:4;49779:1;49782;49785;49763:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49746:41;;49820:1;49802:20;;:6;:20;;;49798:115;;49855:1;49859:29;49898:1;49890:10;;49839:62;;;;;;;;;49798:115;49933:6;49941:20;49971:1;49963:10;;49925:49;;;;;;;48389:1593;;;;;;;;;:::o;50629:542::-;50725:20;50716:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;50712:452;50762:7;50712:452;50823:29;50814:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;50810:354;;50876:23;;;;;;;;;;;;;;50810:354;50930:35;50921:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;50917:247;;51025:8;51017:17;;50989:46;;;;;;;;;;;:::i;:::-;;;;;;;;50917:247;51066:30;51057:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;51053:111;;51143:8;51120:32;;;;;;;;;;;:::i;:::-;;;;;;;;51053:111;50629:542;;;:::o;85016:178::-;85116:12;85148:38;85170:6;85178:4;85184:1;85148:21;:38::i;:::-;85141:45;;85016:178;;;;:::o;8773:415::-;8832:13;8858:11;8872:16;8883:4;8872:10;:16::i;:::-;8858:30;;8978:17;9009:2;8998:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8978:34;;9103:3;9098;9091:16;9144:4;9137;9132:3;9128:14;9121:28;9177:3;9170:10;;;;8773:415;;;:::o;85529:456::-;85662:12;85715:5;85691:21;:29;85687:110;;;85779:4;85744:41;;;;;;;;;;;:::i;:::-;;;;;;;;85687:110;85808:12;85822:23;85849:6;:11;;85868:5;85889:4;85849:55;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85807:97;;;;85922:55;85949:6;85957:7;85966:10;85922:26;:55::i;:::-;85915:62;;;;85529:456;;;;;:::o;9265:251::-;9326:7;9346:14;9399:4;9390;9363:33;;:40;9346:57;;9427:2;9418:6;:11;9414:71;;;9453:20;;;;;;;;;;;;;;9414:71;9502:6;9495:13;;;9265:251;;;:::o;87113:597::-;87261:12;87291:7;87286:417;;87315:19;87323:10;87315:7;:19::i;:::-;87286:417;;;87564:1;87543:10;:17;:22;:49;;;;;87591:1;87569:6;:18;;;:23;87543:49;87539:121;;;87637:6;87620:24;;;;;;;;;;;:::i;:::-;;;;;;;;87539:121;87681:10;87674:17;;;;87286:417;87113:597;;;;;;:::o;88288:528::-;88441:1;88421:10;:17;:21;88417:392;;;88653:10;88647:17;88710:15;88697:10;88693:2;88689:19;88682:44;88417:392;88780:17;;;;;;;;;;;;;;7:75:1;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:117;566:1;563;556:12;580:117;689:1;686;679:12;720:568;793:8;803:6;853:3;846:4;838:6;834:17;830:27;820:122;;861:79;;:::i;:::-;820:122;974:6;961:20;951:30;;1004:18;996:6;993:30;990:117;;;1026:79;;:::i;:::-;990:117;1140:4;1132:6;1128:17;1116:29;;1194:3;1186:4;1178:6;1174:17;1164:8;1160:32;1157:41;1154:128;;;1201:79;;:::i;:::-;1154:128;720:568;;;;;:::o;1294:559::-;1380:6;1388;1437:2;1425:9;1416:7;1412:23;1408:32;1405:119;;;1443:79;;:::i;:::-;1405:119;1591:1;1580:9;1576:17;1563:31;1621:18;1613:6;1610:30;1607:117;;;1643:79;;:::i;:::-;1607:117;1756:80;1828:7;1819:6;1808:9;1804:22;1756:80;:::i;:::-;1738:98;;;;1534:312;1294:559;;;;;:::o;1859:99::-;1911:6;1945:5;1939:12;1929:22;;1859:99;;;:::o;1964:169::-;2048:11;2082:6;2077:3;2070:19;2122:4;2117:3;2113:14;2098:29;;1964:169;;;;:::o;2139:139::-;2228:6;2223:3;2218;2212:23;2269:1;2260:6;2255:3;2251:16;2244:27;2139:139;;;:::o;2284:102::-;2325:6;2376:2;2372:7;2367:2;2360:5;2356:14;2352:28;2342:38;;2284:102;;;:::o;2392:377::-;2480:3;2508:39;2541:5;2508:39;:::i;:::-;2563:71;2627:6;2622:3;2563:71;:::i;:::-;2556:78;;2643:65;2701:6;2696:3;2689:4;2682:5;2678:16;2643:65;:::i;:::-;2733:29;2755:6;2733:29;:::i;:::-;2728:3;2724:39;2717:46;;2484:285;2392:377;;;;:::o;2775:313::-;2888:4;2926:2;2915:9;2911:18;2903:26;;2975:9;2969:4;2965:20;2961:1;2950:9;2946:17;2939:47;3003:78;3076:4;3067:6;3003:78;:::i;:::-;2995:86;;2775:313;;;;:::o;3094:126::-;3131:7;3171:42;3164:5;3160:54;3149:65;;3094:126;;;:::o;3226:96::-;3263:7;3292:24;3310:5;3292:24;:::i;:::-;3281:35;;3226:96;;;:::o;3328:122::-;3401:24;3419:5;3401:24;:::i;:::-;3394:5;3391:35;3381:63;;3440:1;3437;3430:12;3381:63;3328:122;:::o;3456:139::-;3502:5;3540:6;3527:20;3518:29;;3556:33;3583:5;3556:33;:::i;:::-;3456:139;;;;:::o;3601:77::-;3638:7;3667:5;3656:16;;3601:77;;;:::o;3684:122::-;3757:24;3775:5;3757:24;:::i;:::-;3750:5;3747:35;3737:63;;3796:1;3793;3786:12;3737:63;3684:122;:::o;3812:139::-;3858:5;3896:6;3883:20;3874:29;;3912:33;3939:5;3912:33;:::i;:::-;3812:139;;;;:::o;3957:474::-;4025:6;4033;4082:2;4070:9;4061:7;4057:23;4053:32;4050:119;;;4088:79;;:::i;:::-;4050:119;4208:1;4233:53;4278:7;4269:6;4258:9;4254:22;4233:53;:::i;:::-;4223:63;;4179:117;4335:2;4361:53;4406:7;4397:6;4386:9;4382:22;4361:53;:::i;:::-;4351:63;;4306:118;3957:474;;;;;:::o;4437:90::-;4471:7;4514:5;4507:13;4500:21;4489:32;;4437:90;;;:::o;4533:109::-;4614:21;4629:5;4614:21;:::i;:::-;4609:3;4602:34;4533:109;;:::o;4648:210::-;4735:4;4773:2;4762:9;4758:18;4750:26;;4786:65;4848:1;4837:9;4833:17;4824:6;4786:65;:::i;:::-;4648:210;;;;:::o;4864:329::-;4923:6;4972:2;4960:9;4951:7;4947:23;4943:32;4940:119;;;4978:79;;:::i;:::-;4940:119;5098:1;5123:53;5168:7;5159:6;5148:9;5144:22;5123:53;:::i;:::-;5113:63;;5069:117;4864:329;;;;:::o;5199:118::-;5286:24;5304:5;5286:24;:::i;:::-;5281:3;5274:37;5199:118;;:::o;5323:222::-;5416:4;5454:2;5443:9;5439:18;5431:26;;5467:71;5535:1;5524:9;5520:17;5511:6;5467:71;:::i;:::-;5323:222;;;;:::o;5551:110::-;5635:1;5628:5;5625:12;5615:40;;5651:1;5648;5641:12;5615:40;5551:110;:::o;5667:161::-;5724:5;5762:6;5749:20;5740:29;;5778:44;5816:5;5778:44;:::i;:::-;5667:161;;;;:::o;5834:496::-;5913:6;5921;5970:2;5958:9;5949:7;5945:23;5941:32;5938:119;;;5976:79;;:::i;:::-;5938:119;6096:1;6121:64;6177:7;6168:6;6157:9;6153:22;6121:64;:::i;:::-;6111:74;;6067:128;6234:2;6260:53;6305:7;6296:6;6285:9;6281:22;6260:53;:::i;:::-;6250:63;;6205:118;5834:496;;;;;:::o;6336:117::-;6445:1;6442;6435:12;6459:180;6507:77;6504:1;6497:88;6604:4;6601:1;6594:15;6628:4;6625:1;6618:15;6645:281;6728:27;6750:4;6728:27;:::i;:::-;6720:6;6716:40;6858:6;6846:10;6843:22;6822:18;6810:10;6807:34;6804:62;6801:88;;;6869:18;;:::i;:::-;6801:88;6909:10;6905:2;6898:22;6688:238;6645:281;;:::o;6932:129::-;6966:6;6993:20;;:::i;:::-;6983:30;;7022:33;7050:4;7042:6;7022:33;:::i;:::-;6932:129;;;:::o;7067:307::-;7128:4;7218:18;7210:6;7207:30;7204:56;;;7240:18;;:::i;:::-;7204:56;7278:29;7300:6;7278:29;:::i;:::-;7270:37;;7362:4;7356;7352:15;7344:23;;7067:307;;;:::o;7380:148::-;7478:6;7473:3;7468;7455:30;7519:1;7510:6;7505:3;7501:16;7494:27;7380:148;;;:::o;7534:423::-;7611:5;7636:65;7652:48;7693:6;7652:48;:::i;:::-;7636:65;:::i;:::-;7627:74;;7724:6;7717:5;7710:21;7762:4;7755:5;7751:16;7800:3;7791:6;7786:3;7782:16;7779:25;7776:112;;;7807:79;;:::i;:::-;7776:112;7897:54;7944:6;7939:3;7934;7897:54;:::i;:::-;7617:340;7534:423;;;;;:::o;7976:338::-;8031:5;8080:3;8073:4;8065:6;8061:17;8057:27;8047:122;;8088:79;;:::i;:::-;8047:122;8205:6;8192:20;8230:78;8304:3;8296:6;8289:4;8281:6;8277:17;8230:78;:::i;:::-;8221:87;;8037:277;7976:338;;;;:::o;8320:943::-;8415:6;8423;8431;8439;8488:3;8476:9;8467:7;8463:23;8459:33;8456:120;;;8495:79;;:::i;:::-;8456:120;8615:1;8640:53;8685:7;8676:6;8665:9;8661:22;8640:53;:::i;:::-;8630:63;;8586:117;8742:2;8768:53;8813:7;8804:6;8793:9;8789:22;8768:53;:::i;:::-;8758:63;;8713:118;8870:2;8896:53;8941:7;8932:6;8921:9;8917:22;8896:53;:::i;:::-;8886:63;;8841:118;9026:2;9015:9;9011:18;8998:32;9057:18;9049:6;9046:30;9043:117;;;9079:79;;:::i;:::-;9043:117;9184:62;9238:7;9229:6;9218:9;9214:22;9184:62;:::i;:::-;9174:72;;8969:287;8320:943;;;;;;;:::o;9269:149::-;9305:7;9345:66;9338:5;9334:78;9323:89;;9269:149;;;:::o;9424:115::-;9509:23;9526:5;9509:23;:::i;:::-;9504:3;9497:36;9424:115;;:::o;9545:218::-;9636:4;9674:2;9663:9;9659:18;9651:26;;9687:69;9753:1;9742:9;9738:17;9729:6;9687:69;:::i;:::-;9545:218;;;;:::o;9769:114::-;9836:6;9870:5;9864:12;9854:22;;9769:114;;;:::o;9889:184::-;9988:11;10022:6;10017:3;10010:19;10062:4;10057:3;10053:14;10038:29;;9889:184;;;;:::o;10079:132::-;10146:4;10169:3;10161:11;;10199:4;10194:3;10190:14;10182:22;;10079:132;;;:::o;10217:108::-;10294:24;10312:5;10294:24;:::i;:::-;10289:3;10282:37;10217:108;;:::o;10331:179::-;10400:10;10421:46;10463:3;10455:6;10421:46;:::i;:::-;10499:4;10494:3;10490:14;10476:28;;10331:179;;;;:::o;10516:113::-;10586:4;10618;10613:3;10609:14;10601:22;;10516:113;;;:::o;10665:732::-;10784:3;10813:54;10861:5;10813:54;:::i;:::-;10883:86;10962:6;10957:3;10883:86;:::i;:::-;10876:93;;10993:56;11043:5;10993:56;:::i;:::-;11072:7;11103:1;11088:284;11113:6;11110:1;11107:13;11088:284;;;11189:6;11183:13;11216:63;11275:3;11260:13;11216:63;:::i;:::-;11209:70;;11302:60;11355:6;11302:60;:::i;:::-;11292:70;;11148:224;11135:1;11132;11128:9;11123:14;;11088:284;;;11092:14;11388:3;11381:10;;10789:608;;;10665:732;;;;:::o;11403:483::-;11574:4;11612:2;11601:9;11597:18;11589:26;;11661:9;11655:4;11651:20;11647:1;11636:9;11632:17;11625:47;11689:108;11792:4;11783:6;11689:108;:::i;:::-;11681:116;;11807:72;11875:2;11864:9;11860:18;11851:6;11807:72;:::i;:::-;11403:483;;;;;:::o;11892:619::-;11969:6;11977;11985;12034:2;12022:9;12013:7;12009:23;12005:32;12002:119;;;12040:79;;:::i;:::-;12002:119;12160:1;12185:53;12230:7;12221:6;12210:9;12206:22;12185:53;:::i;:::-;12175:63;;12131:117;12287:2;12313:53;12358:7;12349:6;12338:9;12334:22;12313:53;:::i;:::-;12303:63;;12258:118;12415:2;12441:53;12486:7;12477:6;12466:9;12462:22;12441:53;:::i;:::-;12431:63;;12386:118;11892:619;;;;;:::o;12517:351::-;12587:6;12636:2;12624:9;12615:7;12611:23;12607:32;12604:119;;;12642:79;;:::i;:::-;12604:119;12762:1;12787:64;12843:7;12834:6;12823:9;12819:22;12787:64;:::i;:::-;12777:74;;12733:128;12517:351;;;;:::o;12874:86::-;12909:7;12949:4;12942:5;12938:16;12927:27;;12874:86;;;:::o;12966:112::-;13049:22;13065:5;13049:22;:::i;:::-;13044:3;13037:35;12966:112;;:::o;13084:214::-;13173:4;13211:2;13200:9;13196:18;13188:26;;13224:67;13288:1;13277:9;13273:17;13264:6;13224:67;:::i;:::-;13084:214;;;;:::o;13304:77::-;13341:7;13370:5;13359:16;;13304:77;;;:::o;13387:118::-;13474:24;13492:5;13474:24;:::i;:::-;13469:3;13462:37;13387:118;;:::o;13511:222::-;13604:4;13642:2;13631:9;13627:18;13619:26;;13655:71;13723:1;13712:9;13708:17;13699:6;13655:71;:::i;:::-;13511:222;;;;:::o;13739:329::-;13798:6;13847:2;13835:9;13826:7;13822:23;13818:32;13815:119;;;13853:79;;:::i;:::-;13815:119;13973:1;13998:53;14043:7;14034:6;14023:9;14019:22;13998:53;:::i;:::-;13988:63;;13944:117;13739:329;;;;:::o;14074:118::-;14161:24;14179:5;14161:24;:::i;:::-;14156:3;14149:37;14074:118;;:::o;14198:222::-;14291:4;14329:2;14318:9;14314:18;14306:26;;14342:71;14410:1;14399:9;14395:17;14386:6;14342:71;:::i;:::-;14198:222;;;;:::o;14426:311::-;14503:4;14593:18;14585:6;14582:30;14579:56;;;14615:18;;:::i;:::-;14579:56;14665:4;14657:6;14653:17;14645:25;;14725:4;14719;14715:15;14707:23;;14426:311;;;:::o;14760:710::-;14856:5;14881:81;14897:64;14954:6;14897:64;:::i;:::-;14881:81;:::i;:::-;14872:90;;14982:5;15011:6;15004:5;14997:21;15045:4;15038:5;15034:16;15027:23;;15098:4;15090:6;15086:17;15078:6;15074:30;15127:3;15119:6;15116:15;15113:122;;;15146:79;;:::i;:::-;15113:122;15261:6;15244:220;15278:6;15273:3;15270:15;15244:220;;;15353:3;15382:37;15415:3;15403:10;15382:37;:::i;:::-;15377:3;15370:50;15449:4;15444:3;15440:14;15433:21;;15320:144;15304:4;15299:3;15295:14;15288:21;;15244:220;;;15248:21;14862:608;;14760:710;;;;;:::o;15493:370::-;15564:5;15613:3;15606:4;15598:6;15594:17;15590:27;15580:122;;15621:79;;:::i;:::-;15580:122;15738:6;15725:20;15763:94;15853:3;15845:6;15838:4;15830:6;15826:17;15763:94;:::i;:::-;15754:103;;15570:293;15493:370;;;;:::o;15869:539::-;15953:6;16002:2;15990:9;15981:7;15977:23;15973:32;15970:119;;;16008:79;;:::i;:::-;15970:119;16156:1;16145:9;16141:17;16128:31;16186:18;16178:6;16175:30;16172:117;;;16208:79;;:::i;:::-;16172:117;16313:78;16383:7;16374:6;16363:9;16359:22;16313:78;:::i;:::-;16303:88;;16099:302;15869:539;;;;:::o;16414:149::-;16450:7;16490:66;16483:5;16479:78;16468:89;;16414:149;;;:::o;16569:115::-;16654:23;16671:5;16654:23;:::i;:::-;16649:3;16642:36;16569:115;;:::o;16690:1215::-;17039:4;17077:3;17066:9;17062:19;17054:27;;17091:69;17157:1;17146:9;17142:17;17133:6;17091:69;:::i;:::-;17207:9;17201:4;17197:20;17192:2;17181:9;17177:18;17170:48;17235:78;17308:4;17299:6;17235:78;:::i;:::-;17227:86;;17360:9;17354:4;17350:20;17345:2;17334:9;17330:18;17323:48;17388:78;17461:4;17452:6;17388:78;:::i;:::-;17380:86;;17476:72;17544:2;17533:9;17529:18;17520:6;17476:72;:::i;:::-;17558:73;17626:3;17615:9;17611:19;17602:6;17558:73;:::i;:::-;17641;17709:3;17698:9;17694:19;17685:6;17641:73;:::i;:::-;17762:9;17756:4;17752:20;17746:3;17735:9;17731:19;17724:49;17790:108;17893:4;17884:6;17790:108;:::i;:::-;17782:116;;16690:1215;;;;;;;;;;:::o;17911:496::-;17990:6;17998;18047:2;18035:9;18026:7;18022:23;18018:32;18015:119;;;18053:79;;:::i;:::-;18015:119;18173:1;18198:64;18254:7;18245:6;18234:9;18230:22;18198:64;:::i;:::-;18188:74;;18144:128;18311:2;18337:53;18382:7;18373:6;18362:9;18358:22;18337:53;:::i;:::-;18327:63;;18282:118;17911:496;;;;;:::o;18413:442::-;18562:4;18600:2;18589:9;18585:18;18577:26;;18613:71;18681:1;18670:9;18666:17;18657:6;18613:71;:::i;:::-;18694:72;18762:2;18751:9;18747:18;18738:6;18694:72;:::i;:::-;18776;18844:2;18833:9;18829:18;18820:6;18776:72;:::i;:::-;18413:442;;;;;;:::o;18861:118::-;18932:22;18948:5;18932:22;:::i;:::-;18925:5;18922:33;18912:61;;18969:1;18966;18959:12;18912:61;18861:118;:::o;18985:135::-;19029:5;19067:6;19054:20;19045:29;;19083:31;19108:5;19083:31;:::i;:::-;18985:135;;;;:::o;19126:122::-;19199:24;19217:5;19199:24;:::i;:::-;19192:5;19189:35;19179:63;;19238:1;19235;19228:12;19179:63;19126:122;:::o;19254:139::-;19300:5;19338:6;19325:20;19316:29;;19354:33;19381:5;19354:33;:::i;:::-;19254:139;;;;:::o;19399:1199::-;19510:6;19518;19526;19534;19542;19550;19558;19607:3;19595:9;19586:7;19582:23;19578:33;19575:120;;;19614:79;;:::i;:::-;19575:120;19734:1;19759:53;19804:7;19795:6;19784:9;19780:22;19759:53;:::i;:::-;19749:63;;19705:117;19861:2;19887:53;19932:7;19923:6;19912:9;19908:22;19887:53;:::i;:::-;19877:63;;19832:118;19989:2;20015:53;20060:7;20051:6;20040:9;20036:22;20015:53;:::i;:::-;20005:63;;19960:118;20117:2;20143:53;20188:7;20179:6;20168:9;20164:22;20143:53;:::i;:::-;20133:63;;20088:118;20245:3;20272:51;20315:7;20306:6;20295:9;20291:22;20272:51;:::i;:::-;20262:61;;20216:117;20372:3;20399:53;20444:7;20435:6;20424:9;20420:22;20399:53;:::i;:::-;20389:63;;20343:119;20501:3;20528:53;20573:7;20564:6;20553:9;20549:22;20528:53;:::i;:::-;20518:63;;20472:119;19399:1199;;;;;;;;;;:::o;20604:332::-;20725:4;20763:2;20752:9;20748:18;20740:26;;20776:71;20844:1;20833:9;20829:17;20820:6;20776:71;:::i;:::-;20857:72;20925:2;20914:9;20910:18;20901:6;20857:72;:::i;:::-;20604:332;;;;;:::o;20942:474::-;21010:6;21018;21067:2;21055:9;21046:7;21042:23;21038:32;21035:119;;;21073:79;;:::i;:::-;21035:119;21193:1;21218:53;21263:7;21254:6;21243:9;21239:22;21218:53;:::i;:::-;21208:63;;21164:117;21320:2;21346:53;21391:7;21382:6;21371:9;21367:22;21346:53;:::i;:::-;21336:63;;21291:118;20942:474;;;;;:::o;21422:180::-;21470:77;21467:1;21460:88;21567:4;21564:1;21557:15;21591:4;21588:1;21581:15;21608:237;21748:34;21744:1;21736:6;21732:14;21725:58;21817:20;21812:2;21804:6;21800:15;21793:45;21608:237;:::o;21851:366::-;21993:3;22014:67;22078:2;22073:3;22014:67;:::i;:::-;22007:74;;22090:93;22179:3;22090:93;:::i;:::-;22208:2;22203:3;22199:12;22192:19;;21851:366;;;:::o;22223:419::-;22389:4;22427:2;22416:9;22412:18;22404:26;;22476:9;22470:4;22466:20;22462:1;22451:9;22447:17;22440:47;22504:131;22630:4;22504:131;:::i;:::-;22496:139;;22223:419;;;:::o;22648:180::-;22696:77;22693:1;22686:88;22793:4;22790:1;22783:15;22817:4;22814:1;22807:15;22834:194;22874:4;22894:20;22912:1;22894:20;:::i;:::-;22889:25;;22928:20;22946:1;22928:20;:::i;:::-;22923:25;;22972:1;22969;22965:9;22957:17;;22996:1;22990:4;22987:11;22984:37;;;23001:18;;:::i;:::-;22984:37;22834:194;;;;:::o;23034:180::-;23082:77;23079:1;23072:88;23179:4;23176:1;23169:15;23203:4;23200:1;23193:15;23220:442;23369:4;23407:2;23396:9;23392:18;23384:26;;23420:71;23488:1;23477:9;23473:17;23464:6;23420:71;:::i;:::-;23501:72;23569:2;23558:9;23554:18;23545:6;23501:72;:::i;:::-;23583;23651:2;23640:9;23636:18;23627:6;23583:72;:::i;:::-;23220:442;;;;;;:::o;23668:191::-;23708:3;23727:20;23745:1;23727:20;:::i;:::-;23722:25;;23761:20;23779:1;23761:20;:::i;:::-;23756:25;;23804:1;23801;23797:9;23790:16;;23825:3;23822:1;23819:10;23816:36;;;23832:18;;:::i;:::-;23816:36;23668:191;;;;:::o;23865:116::-;23949:1;23942:5;23939:12;23929:46;;23955:18;;:::i;:::-;23929:46;23865:116;:::o;23987:133::-;24035:7;24064:5;24053:16;;24070:44;24108:5;24070:44;:::i;:::-;23987:133;;;:::o;24126:::-;24185:9;24218:35;24247:5;24218:35;:::i;:::-;24205:48;;24126:133;;;:::o;24265:149::-;24361:46;24401:5;24361:46;:::i;:::-;24356:3;24349:59;24265:149;;:::o;24420:117::-;24529:1;24526;24519:12;24543:99;24628:6;24623:3;24618;24605:30;24543:99;;;:::o;24678:537::-;24806:3;24827:86;24906:6;24901:3;24827:86;:::i;:::-;24820:93;;24937:66;24929:6;24926:78;24923:165;;;25007:79;;:::i;:::-;24923:165;25119:4;25111:6;25107:17;25097:27;;25134:43;25170:6;25165:3;25158:5;25134:43;:::i;:::-;25202:6;25197:3;25193:16;25186:23;;24678:537;;;;;:::o;25221:521::-;25411:4;25449:2;25438:9;25434:18;25426:26;;25462:80;25539:1;25528:9;25524:17;25515:6;25462:80;:::i;:::-;25589:9;25583:4;25579:20;25574:2;25563:9;25559:18;25552:48;25617:118;25730:4;25721:6;25713;25617:118;:::i;:::-;25609:126;;25221:521;;;;;;:::o;25748:180::-;25796:77;25793:1;25786:88;25893:4;25890:1;25883:15;25917:4;25914:1;25907:15;25934:320;25978:6;26015:1;26009:4;26005:12;25995:22;;26062:1;26056:4;26052:12;26083:18;26073:81;;26139:4;26131:6;26127:17;26117:27;;26073:81;26201:2;26193:6;26190:14;26170:18;26167:38;26164:84;;26220:18;;:::i;:::-;26164:84;25985:269;25934:320;;;:::o;26260:182::-;26400:34;26396:1;26388:6;26384:14;26377:58;26260:182;:::o;26448:366::-;26590:3;26611:67;26675:2;26670:3;26611:67;:::i;:::-;26604:74;;26687:93;26776:3;26687:93;:::i;:::-;26805:2;26800:3;26796:12;26789:19;;26448:366;;;:::o;26820:419::-;26986:4;27024:2;27013:9;27009:18;27001:26;;27073:9;27067:4;27063:20;27059:1;27048:9;27044:17;27037:47;27101:131;27227:4;27101:131;:::i;:::-;27093:139;;26820:419;;;:::o;27245:227::-;27385:34;27381:1;27373:6;27369:14;27362:58;27454:10;27449:2;27441:6;27437:15;27430:35;27245:227;:::o;27478:366::-;27620:3;27641:67;27705:2;27700:3;27641:67;:::i;:::-;27634:74;;27717:93;27806:3;27717:93;:::i;:::-;27835:2;27830:3;27826:12;27819:19;;27478:366;;;:::o;27850:419::-;28016:4;28054:2;28043:9;28039:18;28031:26;;28103:9;28097:4;28093:20;28089:1;28078:9;28074:17;28067:47;28131:131;28257:4;28131:131;:::i;:::-;28123:139;;27850:419;;;:::o;28275:350::-;28405:4;28443:2;28432:9;28428:18;28420:26;;28456:80;28533:1;28522:9;28518:17;28509:6;28456:80;:::i;:::-;28546:72;28614:2;28603:9;28599:18;28590:6;28546:72;:::i;:::-;28275:350;;;;;:::o;28631:231::-;28771:34;28767:1;28759:6;28755:14;28748:58;28840:14;28835:2;28827:6;28823:15;28816:39;28631:231;:::o;28868:366::-;29010:3;29031:67;29095:2;29090:3;29031:67;:::i;:::-;29024:74;;29107:93;29196:3;29107:93;:::i;:::-;29225:2;29220:3;29216:12;29209:19;;28868:366;;;:::o;29240:419::-;29406:4;29444:2;29433:9;29429:18;29421:26;;29493:9;29487:4;29483:20;29479:1;29468:9;29464:17;29457:47;29521:131;29647:4;29521:131;:::i;:::-;29513:139;;29240:419;;;:::o;29665:170::-;29805:22;29801:1;29793:6;29789:14;29782:46;29665:170;:::o;29841:366::-;29983:3;30004:67;30068:2;30063:3;30004:67;:::i;:::-;29997:74;;30080:93;30169:3;30080:93;:::i;:::-;30198:2;30193:3;30189:12;30182:19;;29841:366;;;:::o;30213:419::-;30379:4;30417:2;30406:9;30402:18;30394:26;;30466:9;30460:4;30456:20;30452:1;30441:9;30437:17;30430:47;30494:131;30620:4;30494:131;:::i;:::-;30486:139;;30213:419;;;:::o;30638:178::-;30778:30;30774:1;30766:6;30762:14;30755:54;30638:178;:::o;30822:366::-;30964:3;30985:67;31049:2;31044:3;30985:67;:::i;:::-;30978:74;;31061:93;31150:3;31061:93;:::i;:::-;31179:2;31174:3;31170:12;31163:19;;30822:366;;;:::o;31194:419::-;31360:4;31398:2;31387:9;31383:18;31375:26;;31447:9;31441:4;31437:20;31433:1;31422:9;31418:17;31411:47;31475:131;31601:4;31475:131;:::i;:::-;31467:139;;31194:419;;;:::o;31619:177::-;31759:29;31755:1;31747:6;31743:14;31736:53;31619:177;:::o;31802:366::-;31944:3;31965:67;32029:2;32024:3;31965:67;:::i;:::-;31958:74;;32041:93;32130:3;32041:93;:::i;:::-;32159:2;32154:3;32150:12;32143:19;;31802:366;;;:::o;32174:419::-;32340:4;32378:2;32367:9;32363:18;32355:26;;32427:9;32421:4;32417:20;32413:1;32402:9;32398:17;32391:47;32455:131;32581:4;32455:131;:::i;:::-;32447:139;;32174:419;;;:::o;32599:180::-;32647:77;32644:1;32637:88;32744:4;32741:1;32734:15;32768:4;32765:1;32758:15;32785:501;32965:4;33003:2;32992:9;32988:18;32980:26;;33016:80;33093:1;33082:9;33078:17;33069:6;33016:80;:::i;:::-;33143:9;33137:4;33133:20;33128:2;33117:9;33113:18;33106:48;33171:108;33274:4;33265:6;33171:108;:::i;:::-;33163:116;;32785:501;;;;;:::o;33292:775::-;33525:4;33563:3;33552:9;33548:19;33540:27;;33577:71;33645:1;33634:9;33630:17;33621:6;33577:71;:::i;:::-;33658:72;33726:2;33715:9;33711:18;33702:6;33658:72;:::i;:::-;33740;33808:2;33797:9;33793:18;33784:6;33740:72;:::i;:::-;33822;33890:2;33879:9;33875:18;33866:6;33822:72;:::i;:::-;33904:73;33972:3;33961:9;33957:19;33948:6;33904:73;:::i;:::-;33987;34055:3;34044:9;34040:19;34031:6;33987:73;:::i;:::-;33292:775;;;;;;;;;:::o;34073:332::-;34194:4;34232:2;34221:9;34217:18;34209:26;;34245:71;34313:1;34302:9;34298:17;34289:6;34245:71;:::i;:::-;34326:72;34394:2;34383:9;34379:18;34370:6;34326:72;:::i;:::-;34073:332;;;;;:::o;34411:220::-;34551:34;34547:1;34539:6;34535:14;34528:58;34620:3;34615:2;34607:6;34603:15;34596:28;34411:220;:::o;34637:366::-;34779:3;34800:67;34864:2;34859:3;34800:67;:::i;:::-;34793:74;;34876:93;34965:3;34876:93;:::i;:::-;34994:2;34989:3;34985:12;34978:19;;34637:366;;;:::o;35009:419::-;35175:4;35213:2;35202:9;35198:18;35190:26;;35262:9;35256:4;35252:20;35248:1;35237:9;35233:17;35226:47;35290:131;35416:4;35290:131;:::i;:::-;35282:139;;35009:419;;;:::o;35434:332::-;35555:4;35593:2;35582:9;35578:18;35570:26;;35606:71;35674:1;35663:9;35659:17;35650:6;35606:71;:::i;:::-;35687:72;35755:2;35744:9;35740:18;35731:6;35687:72;:::i;:::-;35434:332;;;;;:::o;35772:169::-;35912:21;35908:1;35900:6;35896:14;35889:45;35772:169;:::o;35947:366::-;36089:3;36110:67;36174:2;36169:3;36110:67;:::i;:::-;36103:74;;36186:93;36275:3;36186:93;:::i;:::-;36304:2;36299:3;36295:12;36288:19;;35947:366;;;:::o;36319:419::-;36485:4;36523:2;36512:9;36508:18;36500:26;;36572:9;36566:4;36562:20;36558:1;36547:9;36543:17;36536:47;36600:131;36726:4;36600:131;:::i;:::-;36592:139;;36319:419;;;:::o;36744:168::-;36884:20;36880:1;36872:6;36868:14;36861:44;36744:168;:::o;36918:366::-;37060:3;37081:67;37145:2;37140:3;37081:67;:::i;:::-;37074:74;;37157:93;37246:3;37157:93;:::i;:::-;37275:2;37270:3;37266:12;37259:19;;36918:366;;;:::o;37290:419::-;37456:4;37494:2;37483:9;37479:18;37471:26;;37543:9;37537:4;37533:20;37529:1;37518:9;37514:17;37507:47;37571:131;37697:4;37571:131;:::i;:::-;37563:139;;37290:419;;;:::o;37715:410::-;37755:7;37778:20;37796:1;37778:20;:::i;:::-;37773:25;;37812:20;37830:1;37812:20;:::i;:::-;37807:25;;37867:1;37864;37860:9;37889:30;37907:11;37889:30;:::i;:::-;37878:41;;38068:1;38059:7;38055:15;38052:1;38049:22;38029:1;38022:9;38002:83;37979:139;;38098:18;;:::i;:::-;37979:139;37763:362;37715:410;;;;:::o;38131:180::-;38179:77;38176:1;38169:88;38276:4;38273:1;38266:15;38300:4;38297:1;38290:15;38317:185;38357:1;38374:20;38392:1;38374:20;:::i;:::-;38369:25;;38408:20;38426:1;38408:20;:::i;:::-;38403:25;;38447:1;38437:35;;38452:18;;:::i;:::-;38437:35;38494:1;38491;38487:9;38482:14;;38317:185;;;;:::o;38508:442::-;38657:4;38695:2;38684:9;38680:18;38672:26;;38708:71;38776:1;38765:9;38761:17;38752:6;38708:71;:::i;:::-;38789:72;38857:2;38846:9;38842:18;38833:6;38789:72;:::i;:::-;38871;38939:2;38928:9;38924:18;38915:6;38871:72;:::i;:::-;38508:442;;;;;;:::o;38956:116::-;39026:21;39041:5;39026:21;:::i;:::-;39019:5;39016:32;39006:60;;39062:1;39059;39052:12;39006:60;38956:116;:::o;39078:137::-;39132:5;39163:6;39157:13;39148:22;;39179:30;39203:5;39179:30;:::i;:::-;39078:137;;;;:::o;39221:345::-;39288:6;39337:2;39325:9;39316:7;39312:23;39308:32;39305:119;;;39343:79;;:::i;:::-;39305:119;39463:1;39488:61;39541:7;39532:6;39521:9;39517:22;39488:61;:::i;:::-;39478:71;;39434:125;39221:345;;;;:::o;39572:664::-;39777:4;39815:3;39804:9;39800:19;39792:27;;39829:71;39897:1;39886:9;39882:17;39873:6;39829:71;:::i;:::-;39910:72;39978:2;39967:9;39963:18;39954:6;39910:72;:::i;:::-;39992;40060:2;40049:9;40045:18;40036:6;39992:72;:::i;:::-;40074;40142:2;40131:9;40127:18;40118:6;40074:72;:::i;:::-;40156:73;40224:3;40213:9;40209:19;40200:6;40156:73;:::i;:::-;39572:664;;;;;;;;:::o;40242:545::-;40415:4;40453:3;40442:9;40438:19;40430:27;;40467:71;40535:1;40524:9;40520:17;40511:6;40467:71;:::i;:::-;40548:68;40612:2;40601:9;40597:18;40588:6;40548:68;:::i;:::-;40626:72;40694:2;40683:9;40679:18;40670:6;40626:72;:::i;:::-;40708;40776:2;40765:9;40761:18;40752:6;40708:72;:::i;:::-;40242:545;;;;;;;:::o;40793:98::-;40844:6;40878:5;40872:12;40862:22;;40793:98;;;:::o;40897:147::-;40998:11;41035:3;41020:18;;40897:147;;;;:::o;41050:386::-;41154:3;41182:38;41214:5;41182:38;:::i;:::-;41236:88;41317:6;41312:3;41236:88;:::i;:::-;41229:95;;41333:65;41391:6;41386:3;41379:4;41372:5;41368:16;41333:65;:::i;:::-;41423:6;41418:3;41414:16;41407:23;;41158:278;41050:386;;;;:::o;41442:271::-;41572:3;41594:93;41683:3;41674:6;41594:93;:::i;:::-;41587:100;;41704:3;41697:10;;41442:271;;;;:::o

Swarm Source

ipfs://ac2268774346f622e49c4b552a07268603e4669d074afd830f259c3c471245b3

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

OVERVIEW

NCASH is a staking memecoin deployed on Arbitrum One with a fixed capped supply.

Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.