ETH Price: $3,432.69 (+2.49%)

Token

FARTS (FARTS)
 

Overview

Max Total Supply

1,000,000,000 FARTS

Holders

246

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
bored-duck.eth
Balance
1,000,084.244150938705639554 FARTS

Value
$0.00
0xbfc59f03368822bf381c1995df910a24300a23ab
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
MyERC20Token

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-12-17
*/

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


// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;


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

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated 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/contracts/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/contracts/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: allowlist.sol


pragma solidity ^0.8.23;





contract MyERC20Token is ERC20, Ownable {
    using ECDSA for bytes32;

    uint256 public MAX_SUPPLY;
    uint256 public MAX_MINT_PER_ADDRESS;
    uint256 public constant PRICE_PER_HUNDRED_TOKENS = 0.0001 ether;
    uint256 public MINT_INCREMENT;
    uint256 public constant LAST_PRE_PERMISSIONLESS_FID = 20939;

    address public signerAddress;
    address public constant PURPLE_DAO_TREASURY =
        0xeB5977F7630035fe3b28f11F9Cb5be9F01A9557D;

    mapping(address => uint256) public mintedAmounts;

    constructor(address initialOwner)
        ERC20("FARTS", "FARTS")
        Ownable(initialOwner)
    {
        signerAddress = initialOwner;
        MAX_SUPPLY = 1000000000 * 10**decimals();
        MAX_MINT_PER_ADDRESS = 20000000 * 10**decimals();
        MINT_INCREMENT = 100 * 10**decimals();
    }

    function mint(uint256 numberOfHundreds) public payable {
        uint256 tokensToMint = numberOfHundreds * MINT_INCREMENT;
        require(
            mintedAmounts[msg.sender] + tokensToMint <= MAX_MINT_PER_ADDRESS,
            "Mint limit exceeded"
        );
        require(
            totalSupply() + tokensToMint <= MAX_SUPPLY,
            "Max supply exceeded"
        );

        uint256 requiredPayment = numberOfHundreds * PRICE_PER_HUNDRED_TOKENS;
        require(msg.value >= requiredPayment, "Insufficient ETH sent");

        _mint(msg.sender, tokensToMint);
        mintedAmounts[msg.sender] += tokensToMint;

        if (msg.value > requiredPayment) {
            payable(msg.sender).transfer(msg.value - requiredPayment);
        }
    }

    function mintWithFid(
        uint256 numberOfHundreds,
        uint256 farcasterId,
        bytes memory signature
    ) public payable {
        require(farcasterId > 0, "FID must be a positive integer");
        uint256 tokensToMint = numberOfHundreds * MINT_INCREMENT;
        require(
            mintedAmounts[msg.sender] + tokensToMint <= MAX_MINT_PER_ADDRESS,
            "Mint limit exceeded"
        );
        require(
            totalSupply() + tokensToMint <= MAX_SUPPLY,
            "Max supply exceeded"
        );

        bytes32 message = keccak256(abi.encodePacked(msg.sender, farcasterId));
        bytes32 signedMessageHash = MessageHashUtils.toEthSignedMessageHash(
            message
        );
        require(
            signedMessageHash.recover(signature) == signerAddress,
            "Invalid signature"
        );

        uint256 unitPrice = calculateUnitPrice(farcasterId);
        uint256 cost = unitPrice * numberOfHundreds;
        require(msg.value >= cost, "Insufficient ETH sent");

        _mint(msg.sender, tokensToMint);
        mintedAmounts[msg.sender] += tokensToMint;

        if (msg.value > cost) {
            payable(msg.sender).transfer(msg.value - cost);
        }
    }

    function calculateUnitPrice(uint256 farcasterId)
        internal
        pure
        returns (uint256)
    {
        uint256 newPricePct;

        if (farcasterId >= 1 && farcasterId <= LAST_PRE_PERMISSIONLESS_FID) {
            // new price scales linearly between 10% (fid=0) and 90% (fid=LAST_PRE_PERMISSIONLESS_FID)
            newPricePct = 10 + (farcasterId * 80) / LAST_PRE_PERMISSIONLESS_FID;
        } else {
            newPricePct = 90;
        }

        return (PRICE_PER_HUNDRED_TOKENS * newPricePct) / 100;
    }

    function remainingMintQuota(address user) public view returns (uint256) {
        return MAX_MINT_PER_ADDRESS - mintedAmounts[user];
    }

    function airdrop(address to, uint256 amount) public onlyOwner {
        _airdrop(to, amount);
    }

    function batchAirdrop(address[] memory recipients, uint256[] memory amounts)
        public
        onlyOwner
    {
        require(
            recipients.length == amounts.length,
            "Mismatched array lengths"
        );

        for (uint256 i = 0; i < recipients.length; i++) {
            _airdrop(recipients[i], amounts[i]);
        }
    }

    function _airdrop(address recipient, uint256 amount) internal {
        uint256 amountWithDecimals = amount * 10**decimals();
        require(
            totalSupply() + amountWithDecimals <= MAX_SUPPLY,
            "Max supply exceeded"
        );
        _mint(recipient, amountWithDecimals);
    }

    function withdrawToPurple() public onlyOwner {
        payable(PURPLE_DAO_TREASURY).transfer(address(this).balance);
    }

    function setSignerAddress(address _signerAddress) external onlyOwner {
        signerAddress = _signerAddress;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"LAST_PRE_PERMISSIONLESS_FID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MINT_PER_ADDRESS","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":"MINT_INCREMENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_PER_HUNDRED_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PURPLE_DAO_TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","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":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"batchAirdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfHundreds","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfHundreds","type":"uint256"},{"internalType":"uint256","name":"farcasterId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mintWithFid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintedAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"remainingMintQuota","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signerAddress","type":"address"}],"name":"setSignerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"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":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawToPurple","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801562000010575f80fd5b506040516200333738038062003337833981810160405281019062000036919062000361565b806040518060400160405280600581526020017f46415254530000000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f46415254530000000000000000000000000000000000000000000000000000008152508160039081620000b49190620005f5565b508060049081620000c69190620005f5565b5050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200013c575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620001339190620006ea565b60405180910390fd5b6200014d816200023160201b60201c565b508060095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506200019e620002f460201b60201c565b600a620001ac91906200088e565b633b9aca00620001bd9190620008de565b600681905550620001d3620002f460201b60201c565b600a620001e191906200088e565b6301312d00620001f29190620008de565b60078190555062000208620002f460201b60201c565b600a6200021691906200088e565b6064620002249190620008de565b6008819055505062000928565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6012905090565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6200032b8262000300565b9050919050565b6200033d816200031f565b811462000348575f80fd5b50565b5f815190506200035b8162000332565b92915050565b5f60208284031215620003795762000378620002fc565b5b5f62000388848285016200034b565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200040d57607f821691505b602082108103620004235762000422620003c8565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620004877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200044a565b6200049386836200044a565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004dd620004d7620004d184620004ab565b620004b4565b620004ab565b9050919050565b5f819050919050565b620004f883620004bd565b620005106200050782620004e4565b84845462000456565b825550505050565b5f90565b6200052662000518565b62000533818484620004ed565b505050565b5b818110156200055a576200054e5f826200051c565b60018101905062000539565b5050565b601f821115620005a957620005738162000429565b6200057e846200043b565b810160208510156200058e578190505b620005a66200059d856200043b565b83018262000538565b50505b505050565b5f82821c905092915050565b5f620005cb5f1984600802620005ae565b1980831691505092915050565b5f620005e58383620005ba565b9150826002028217905092915050565b620006008262000391565b67ffffffffffffffff8111156200061c576200061b6200039b565b5b620006288254620003f5565b620006358282856200055e565b5f60209050601f8311600181146200066b575f841562000656578287015190505b620006628582620005d8565b865550620006d1565b601f1984166200067b8662000429565b5f5b82811015620006a4578489015182556001820191506020850194506020810190506200067d565b86831015620006c45784890151620006c0601f891682620005ba565b8355505b6001600288020188555050505b505050505050565b620006e4816200031f565b82525050565b5f602082019050620006ff5f830184620006d9565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f808291508390505b60018511156200078f5780860481111562000767576200076662000705565b5b6001851615620007775780820291505b8081029050620007878562000732565b945062000747565b94509492505050565b5f82620007a957600190506200087b565b81620007b8575f90506200087b565b8160018114620007d15760028114620007dc5762000812565b60019150506200087b565b60ff841115620007f157620007f062000705565b5b8360020a9150848211156200080b576200080a62000705565b5b506200087b565b5060208310610133831016604e8410600b84101617156200084c5782820a90508381111562000846576200084562000705565b5b6200087b565b6200085b84848460016200073e565b9250905081840481111562000875576200087462000705565b5b81810290505b9392505050565b5f60ff82169050919050565b5f6200089a82620004ab565b9150620008a78362000882565b9250620008d67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848462000798565b905092915050565b5f620008ea82620004ab565b9150620008f783620004ab565b92508282026200090781620004ab565b9150828204841483151762000921576200092062000705565b5b5092915050565b612a0180620009365f395ff3fe60806040526004361061019b575f3560e01c8063715018a6116100eb578063a9059cbb11610089578063c3321e1211610063578063c3321e1214610595578063c45e8c7f146105b1578063dd62ed3e146105db578063f2fde38b146106175761019b565b8063a9059cbb14610507578063abcf71ba14610543578063b816d0871461056d5761019b565b80638da5cb5b116100c55780638da5cb5b1461048157806395d89b41146104ab578063a0712d68146104d5578063a79066ff146104f15761019b565b8063715018a6146104195780637675dc381461042f5780638ba4cc3c146104595761019b565b8063313ce567116101585780633acd6cb2116101325780633acd6cb21461034d5780635b7633d0146103775780636ef0d855146103a157806370a08231146103dd5761019b565b8063313ce567146102cf57806332cb6b0c146102f95780633a6604a7146103235761019b565b8063046dc1661461019f57806306fdde03146101c7578063095ea7b3146101f157806318160ddd1461022d5780632066d7b81461025757806323b872dd14610293575b5f80fd5b3480156101aa575f80fd5b506101c560048036038101906101c09190611c79565b61063f565b005b3480156101d2575f80fd5b506101db61068a565b6040516101e89190611d2e565b60405180910390f35b3480156101fc575f80fd5b5061021760048036038101906102129190611d81565b61071a565b6040516102249190611dd9565b60405180910390f35b348015610238575f80fd5b5061024161073c565b60405161024e9190611e01565b60405180910390f35b348015610262575f80fd5b5061027d60048036038101906102789190611c79565b610745565b60405161028a9190611e01565b60405180910390f35b34801561029e575f80fd5b506102b960048036038101906102b49190611e1a565b610798565b6040516102c69190611dd9565b60405180910390f35b3480156102da575f80fd5b506102e36107c6565b6040516102f09190611e85565b60405180910390f35b348015610304575f80fd5b5061030d6107ce565b60405161031a9190611e01565b60405180910390f35b34801561032e575f80fd5b506103376107d4565b6040516103449190611e01565b60405180910390f35b348015610358575f80fd5b506103616107da565b60405161036e9190611e01565b60405180910390f35b348015610382575f80fd5b5061038b6107e0565b6040516103989190611ead565b60405180910390f35b3480156103ac575f80fd5b506103c760048036038101906103c29190611c79565b610805565b6040516103d49190611e01565b60405180910390f35b3480156103e8575f80fd5b5061040360048036038101906103fe9190611c79565b61081a565b6040516104109190611e01565b60405180910390f35b348015610424575f80fd5b5061042d61085f565b005b34801561043a575f80fd5b50610443610872565b6040516104509190611ead565b60405180910390f35b348015610464575f80fd5b5061047f600480360381019061047a9190611d81565b61088a565b005b34801561048c575f80fd5b506104956108a0565b6040516104a29190611ead565b60405180910390f35b3480156104b6575f80fd5b506104bf6108c8565b6040516104cc9190611d2e565b60405180910390f35b6104ef60048036038101906104ea9190611ec6565b610958565b005b3480156104fc575f80fd5b50610505610b5f565b005b348015610512575f80fd5b5061052d60048036038101906105289190611d81565b610bc1565b60405161053a9190611dd9565b60405180910390f35b34801561054e575f80fd5b50610557610be3565b6040516105649190611e01565b60405180910390f35b348015610578575f80fd5b50610593600480360381019061058e91906120f1565b610bed565b005b6105af60048036038101906105aa9190612217565b610c94565b005b3480156105bc575f80fd5b506105c5610fc1565b6040516105d29190611e01565b60405180910390f35b3480156105e6575f80fd5b5061060160048036038101906105fc9190612283565b610fc7565b60405161060e9190611e01565b60405180910390f35b348015610622575f80fd5b5061063d60048036038101906106389190611c79565b611049565b005b6106476110cd565b8060095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b606060038054610699906122ee565b80601f01602080910402602001604051908101604052809291908181526020018280546106c5906122ee565b80156107105780601f106106e757610100808354040283529160200191610710565b820191905f5260205f20905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b5f80610724611154565b905061073181858561115b565b600191505092915050565b5f600254905090565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054600754610791919061234b565b9050919050565b5f806107a2611154565b90506107af85828561116d565b6107ba8585856111ff565b60019150509392505050565b5f6012905090565b60065481565b6151cb81565b60075481565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a602052805f5260405f205f915090505481565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6108676110cd565b6108705f6112ef565b565b73eb5977f7630035fe3b28f11f9cb5be9f01a9557d81565b6108926110cd565b61089c82826113b2565b5050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600480546108d7906122ee565b80601f0160208091040260200160405190810160405280929190818152602001828054610903906122ee565b801561094e5780601f106109255761010080835404028352916020019161094e565b820191905f5260205f20905b81548152906001019060200180831161093157829003601f168201915b5050505050905090565b5f60085482610967919061237e565b905060075481600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546109b591906123bf565b11156109f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ed9061243c565b60405180910390fd5b60065481610a0261073c565b610a0c91906123bf565b1115610a4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a44906124a4565b60405180910390fd5b5f655af3107a400083610a60919061237e565b905080341015610aa5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9c9061250c565b60405180910390fd5b610aaf338361143a565b81600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610afb91906123bf565b9250508190555080341115610b5a573373ffffffffffffffffffffffffffffffffffffffff166108fc8234610b30919061234b565b90811502906040515f60405180830381858888f19350505050158015610b58573d5f803e3d5ffd5b505b505050565b610b676110cd565b73eb5977f7630035fe3b28f11f9cb5be9f01a9557d73ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015610bbe573d5f803e3d5ffd5b50565b5f80610bcb611154565b9050610bd88185856111ff565b600191505092915050565b655af3107a400081565b610bf56110cd565b8051825114610c39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3090612574565b60405180910390fd5b5f5b8251811015610c8f57610c82838281518110610c5a57610c59612592565b5b6020026020010151838381518110610c7557610c74612592565b5b60200260200101516113b2565b8080600101915050610c3b565b505050565b5f8211610cd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ccd90612609565b60405180910390fd5b5f60085484610ce5919061237e565b905060075481600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054610d3391906123bf565b1115610d74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6b9061243c565b60405180910390fd5b60065481610d8061073c565b610d8a91906123bf565b1115610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc2906124a4565b60405180910390fd5b5f3384604051602001610ddf92919061268c565b6040516020818303038152906040528051906020012090505f610e01826114b9565b905060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610e4e85836114ec90919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff1614610ea4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9b90612701565b60405180910390fd5b5f610eae86611516565b90505f8782610ebd919061237e565b905080341015610f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef99061250c565b60405180910390fd5b610f0c338661143a565b84600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610f5891906123bf565b9250508190555080341115610fb7573373ffffffffffffffffffffffffffffffffffffffff166108fc8234610f8d919061234b565b90811502906040515f60405180830381858888f19350505050158015610fb5573d5f803e3d5ffd5b505b5050505050505050565b60085481565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b6110516110cd565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036110c1575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016110b89190611ead565b60405180910390fd5b6110ca816112ef565b50565b6110d5611154565b73ffffffffffffffffffffffffffffffffffffffff166110f36108a0565b73ffffffffffffffffffffffffffffffffffffffff161461115257611116611154565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016111499190611ead565b60405180910390fd5b565b5f33905090565b6111688383836001611588565b505050565b5f6111788484610fc7565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146111f957818110156111ea578281836040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526004016111e19392919061271f565b60405180910390fd5b6111f884848484035f611588565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361126f575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016112669190611ead565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036112df575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016112d69190611ead565b60405180910390fd5b6112ea838383611757565b505050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6113bb6107c6565b600a6113c79190612883565b826113d2919061237e565b9050600654816113e061073c565b6113ea91906123bf565b111561142b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611422906124a4565b60405180910390fd5b611435838261143a565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036114aa575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016114a19190611ead565b60405180910390fd5b6114b55f8383611757565b5050565b5f7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f5281601c52603c5f209050919050565b5f805f806114fa8686611970565b92509250925061150a82826119c5565b82935050505092915050565b5f806001831015801561152b57506151cb8311155b1561155d576151cb605084611540919061237e565b61154a91906128fa565b600a61155691906123bf565b9050611562565b605a90505b606481655af3107a4000611576919061237e565b61158091906128fa565b915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036115f8575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016115ef9190611ead565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611668575f6040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161165f9190611ead565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015611751578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516117489190611e01565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117a7578060025f82825461179b91906123bf565b92505081905550611875565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611830578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016118279392919061271f565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118bc578060025f8282540392505081905550611906565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516119639190611e01565b60405180910390a3505050565b5f805f60418451036119b0575f805f602087015192506040870151915060608701515f1a90506119a288828585611b27565b9550955095505050506119be565b5f600285515f1b9250925092505b9250925092565b5f60038111156119d8576119d761292a565b5b8260038111156119eb576119ea61292a565b5b0315611b235760016003811115611a0557611a0461292a565b5b826003811115611a1857611a1761292a565b5b03611a4f576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115611a6357611a6261292a565b5b826003811115611a7657611a7561292a565b5b03611aba57805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401611ab19190611e01565b60405180910390fd5b600380811115611acd57611acc61292a565b5b826003811115611ae057611adf61292a565b5b03611b2257806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401611b19919061296f565b60405180910390fd5b5b5050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115611b63575f600385925092509250611c04565b5f6001888888886040515f8152602001604052604051611b869493929190612988565b6020604051602081039080840390855afa158015611ba6573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611bf7575f60015f801b93509350935050611c04565b805f805f1b935093509350505b9450945094915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611c4882611c1f565b9050919050565b611c5881611c3e565b8114611c62575f80fd5b50565b5f81359050611c7381611c4f565b92915050565b5f60208284031215611c8e57611c8d611c17565b5b5f611c9b84828501611c65565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611cdb578082015181840152602081019050611cc0565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611d0082611ca4565b611d0a8185611cae565b9350611d1a818560208601611cbe565b611d2381611ce6565b840191505092915050565b5f6020820190508181035f830152611d468184611cf6565b905092915050565b5f819050919050565b611d6081611d4e565b8114611d6a575f80fd5b50565b5f81359050611d7b81611d57565b92915050565b5f8060408385031215611d9757611d96611c17565b5b5f611da485828601611c65565b9250506020611db585828601611d6d565b9150509250929050565b5f8115159050919050565b611dd381611dbf565b82525050565b5f602082019050611dec5f830184611dca565b92915050565b611dfb81611d4e565b82525050565b5f602082019050611e145f830184611df2565b92915050565b5f805f60608486031215611e3157611e30611c17565b5b5f611e3e86828701611c65565b9350506020611e4f86828701611c65565b9250506040611e6086828701611d6d565b9150509250925092565b5f60ff82169050919050565b611e7f81611e6a565b82525050565b5f602082019050611e985f830184611e76565b92915050565b611ea781611c3e565b82525050565b5f602082019050611ec05f830184611e9e565b92915050565b5f60208284031215611edb57611eda611c17565b5b5f611ee884828501611d6d565b91505092915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b611f2b82611ce6565b810181811067ffffffffffffffff82111715611f4a57611f49611ef5565b5b80604052505050565b5f611f5c611c0e565b9050611f688282611f22565b919050565b5f67ffffffffffffffff821115611f8757611f86611ef5565b5b602082029050602081019050919050565b5f80fd5b5f611fae611fa984611f6d565b611f53565b90508083825260208201905060208402830185811115611fd157611fd0611f98565b5b835b81811015611ffa5780611fe68882611c65565b845260208401935050602081019050611fd3565b5050509392505050565b5f82601f83011261201857612017611ef1565b5b8135612028848260208601611f9c565b91505092915050565b5f67ffffffffffffffff82111561204b5761204a611ef5565b5b602082029050602081019050919050565b5f61206e61206984612031565b611f53565b9050808382526020820190506020840283018581111561209157612090611f98565b5b835b818110156120ba57806120a68882611d6d565b845260208401935050602081019050612093565b5050509392505050565b5f82601f8301126120d8576120d7611ef1565b5b81356120e884826020860161205c565b91505092915050565b5f806040838503121561210757612106611c17565b5b5f83013567ffffffffffffffff81111561212457612123611c1b565b5b61213085828601612004565b925050602083013567ffffffffffffffff81111561215157612150611c1b565b5b61215d858286016120c4565b9150509250929050565b5f80fd5b5f67ffffffffffffffff82111561218557612184611ef5565b5b61218e82611ce6565b9050602081019050919050565b828183375f83830152505050565b5f6121bb6121b68461216b565b611f53565b9050828152602081018484840111156121d7576121d6612167565b5b6121e284828561219b565b509392505050565b5f82601f8301126121fe576121fd611ef1565b5b813561220e8482602086016121a9565b91505092915050565b5f805f6060848603121561222e5761222d611c17565b5b5f61223b86828701611d6d565b935050602061224c86828701611d6d565b925050604084013567ffffffffffffffff81111561226d5761226c611c1b565b5b612279868287016121ea565b9150509250925092565b5f806040838503121561229957612298611c17565b5b5f6122a685828601611c65565b92505060206122b785828601611c65565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061230557607f821691505b602082108103612318576123176122c1565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61235582611d4e565b915061236083611d4e565b92508282039050818111156123785761237761231e565b5b92915050565b5f61238882611d4e565b915061239383611d4e565b92508282026123a181611d4e565b915082820484148315176123b8576123b761231e565b5b5092915050565b5f6123c982611d4e565b91506123d483611d4e565b92508282019050808211156123ec576123eb61231e565b5b92915050565b7f4d696e74206c696d6974206578636565646564000000000000000000000000005f82015250565b5f612426601383611cae565b9150612431826123f2565b602082019050919050565b5f6020820190508181035f8301526124538161241a565b9050919050565b7f4d617820737570706c79206578636565646564000000000000000000000000005f82015250565b5f61248e601383611cae565b91506124998261245a565b602082019050919050565b5f6020820190508181035f8301526124bb81612482565b9050919050565b7f496e73756666696369656e74204554482073656e7400000000000000000000005f82015250565b5f6124f6601583611cae565b9150612501826124c2565b602082019050919050565b5f6020820190508181035f830152612523816124ea565b9050919050565b7f4d69736d617463686564206172726179206c656e6774687300000000000000005f82015250565b5f61255e601883611cae565b91506125698261252a565b602082019050919050565b5f6020820190508181035f83015261258b81612552565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f464944206d757374206265206120706f73697469766520696e746567657200005f82015250565b5f6125f3601e83611cae565b91506125fe826125bf565b602082019050919050565b5f6020820190508181035f830152612620816125e7565b9050919050565b5f8160601b9050919050565b5f61263d82612627565b9050919050565b5f61264e82612633565b9050919050565b61266661266182611c3e565b612644565b82525050565b5f819050919050565b61268661268182611d4e565b61266c565b82525050565b5f6126978285612655565b6014820191506126a78284612675565b6020820191508190509392505050565b7f496e76616c6964207369676e61747572650000000000000000000000000000005f82015250565b5f6126eb601183611cae565b91506126f6826126b7565b602082019050919050565b5f6020820190508181035f830152612718816126df565b9050919050565b5f6060820190506127325f830186611e9e565b61273f6020830185611df2565b61274c6040830184611df2565b949350505050565b5f8160011c9050919050565b5f808291508390505b60018511156127a9578086048111156127855761278461231e565b5b60018516156127945780820291505b80810290506127a285612754565b9450612769565b94509492505050565b5f826127c1576001905061287c565b816127ce575f905061287c565b81600181146127e457600281146127ee5761281d565b600191505061287c565b60ff841115612800576127ff61231e565b5b8360020a9150848211156128175761281661231e565b5b5061287c565b5060208310610133831016604e8410600b84101617156128525782820a90508381111561284d5761284c61231e565b5b61287c565b61285f8484846001612760565b925090508184048111156128765761287561231e565b5b81810290505b9392505050565b5f61288d82611d4e565b915061289883611e6a565b92506128c57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846127b2565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61290482611d4e565b915061290f83611d4e565b92508261291f5761291e6128cd565b5b828204905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f819050919050565b61296981612957565b82525050565b5f6020820190506129825f830184612960565b92915050565b5f60808201905061299b5f830187612960565b6129a86020830186611e76565b6129b56040830185612960565b6129c26060830184612960565b9594505050505056fea2646970667358221220c42118c3525263de6d908f7676b7de49237a1d9bfd251112afe1cb1786e03b7e64736f6c63430008170033000000000000000000000000dd94873dd3d62233ab263d038091c84fcd247a4c

Deployed Bytecode

0x60806040526004361061019b575f3560e01c8063715018a6116100eb578063a9059cbb11610089578063c3321e1211610063578063c3321e1214610595578063c45e8c7f146105b1578063dd62ed3e146105db578063f2fde38b146106175761019b565b8063a9059cbb14610507578063abcf71ba14610543578063b816d0871461056d5761019b565b80638da5cb5b116100c55780638da5cb5b1461048157806395d89b41146104ab578063a0712d68146104d5578063a79066ff146104f15761019b565b8063715018a6146104195780637675dc381461042f5780638ba4cc3c146104595761019b565b8063313ce567116101585780633acd6cb2116101325780633acd6cb21461034d5780635b7633d0146103775780636ef0d855146103a157806370a08231146103dd5761019b565b8063313ce567146102cf57806332cb6b0c146102f95780633a6604a7146103235761019b565b8063046dc1661461019f57806306fdde03146101c7578063095ea7b3146101f157806318160ddd1461022d5780632066d7b81461025757806323b872dd14610293575b5f80fd5b3480156101aa575f80fd5b506101c560048036038101906101c09190611c79565b61063f565b005b3480156101d2575f80fd5b506101db61068a565b6040516101e89190611d2e565b60405180910390f35b3480156101fc575f80fd5b5061021760048036038101906102129190611d81565b61071a565b6040516102249190611dd9565b60405180910390f35b348015610238575f80fd5b5061024161073c565b60405161024e9190611e01565b60405180910390f35b348015610262575f80fd5b5061027d60048036038101906102789190611c79565b610745565b60405161028a9190611e01565b60405180910390f35b34801561029e575f80fd5b506102b960048036038101906102b49190611e1a565b610798565b6040516102c69190611dd9565b60405180910390f35b3480156102da575f80fd5b506102e36107c6565b6040516102f09190611e85565b60405180910390f35b348015610304575f80fd5b5061030d6107ce565b60405161031a9190611e01565b60405180910390f35b34801561032e575f80fd5b506103376107d4565b6040516103449190611e01565b60405180910390f35b348015610358575f80fd5b506103616107da565b60405161036e9190611e01565b60405180910390f35b348015610382575f80fd5b5061038b6107e0565b6040516103989190611ead565b60405180910390f35b3480156103ac575f80fd5b506103c760048036038101906103c29190611c79565b610805565b6040516103d49190611e01565b60405180910390f35b3480156103e8575f80fd5b5061040360048036038101906103fe9190611c79565b61081a565b6040516104109190611e01565b60405180910390f35b348015610424575f80fd5b5061042d61085f565b005b34801561043a575f80fd5b50610443610872565b6040516104509190611ead565b60405180910390f35b348015610464575f80fd5b5061047f600480360381019061047a9190611d81565b61088a565b005b34801561048c575f80fd5b506104956108a0565b6040516104a29190611ead565b60405180910390f35b3480156104b6575f80fd5b506104bf6108c8565b6040516104cc9190611d2e565b60405180910390f35b6104ef60048036038101906104ea9190611ec6565b610958565b005b3480156104fc575f80fd5b50610505610b5f565b005b348015610512575f80fd5b5061052d60048036038101906105289190611d81565b610bc1565b60405161053a9190611dd9565b60405180910390f35b34801561054e575f80fd5b50610557610be3565b6040516105649190611e01565b60405180910390f35b348015610578575f80fd5b50610593600480360381019061058e91906120f1565b610bed565b005b6105af60048036038101906105aa9190612217565b610c94565b005b3480156105bc575f80fd5b506105c5610fc1565b6040516105d29190611e01565b60405180910390f35b3480156105e6575f80fd5b5061060160048036038101906105fc9190612283565b610fc7565b60405161060e9190611e01565b60405180910390f35b348015610622575f80fd5b5061063d60048036038101906106389190611c79565b611049565b005b6106476110cd565b8060095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b606060038054610699906122ee565b80601f01602080910402602001604051908101604052809291908181526020018280546106c5906122ee565b80156107105780601f106106e757610100808354040283529160200191610710565b820191905f5260205f20905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b5f80610724611154565b905061073181858561115b565b600191505092915050565b5f600254905090565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054600754610791919061234b565b9050919050565b5f806107a2611154565b90506107af85828561116d565b6107ba8585856111ff565b60019150509392505050565b5f6012905090565b60065481565b6151cb81565b60075481565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a602052805f5260405f205f915090505481565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6108676110cd565b6108705f6112ef565b565b73eb5977f7630035fe3b28f11f9cb5be9f01a9557d81565b6108926110cd565b61089c82826113b2565b5050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600480546108d7906122ee565b80601f0160208091040260200160405190810160405280929190818152602001828054610903906122ee565b801561094e5780601f106109255761010080835404028352916020019161094e565b820191905f5260205f20905b81548152906001019060200180831161093157829003601f168201915b5050505050905090565b5f60085482610967919061237e565b905060075481600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546109b591906123bf565b11156109f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ed9061243c565b60405180910390fd5b60065481610a0261073c565b610a0c91906123bf565b1115610a4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a44906124a4565b60405180910390fd5b5f655af3107a400083610a60919061237e565b905080341015610aa5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9c9061250c565b60405180910390fd5b610aaf338361143a565b81600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610afb91906123bf565b9250508190555080341115610b5a573373ffffffffffffffffffffffffffffffffffffffff166108fc8234610b30919061234b565b90811502906040515f60405180830381858888f19350505050158015610b58573d5f803e3d5ffd5b505b505050565b610b676110cd565b73eb5977f7630035fe3b28f11f9cb5be9f01a9557d73ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015610bbe573d5f803e3d5ffd5b50565b5f80610bcb611154565b9050610bd88185856111ff565b600191505092915050565b655af3107a400081565b610bf56110cd565b8051825114610c39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3090612574565b60405180910390fd5b5f5b8251811015610c8f57610c82838281518110610c5a57610c59612592565b5b6020026020010151838381518110610c7557610c74612592565b5b60200260200101516113b2565b8080600101915050610c3b565b505050565b5f8211610cd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ccd90612609565b60405180910390fd5b5f60085484610ce5919061237e565b905060075481600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054610d3391906123bf565b1115610d74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6b9061243c565b60405180910390fd5b60065481610d8061073c565b610d8a91906123bf565b1115610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc2906124a4565b60405180910390fd5b5f3384604051602001610ddf92919061268c565b6040516020818303038152906040528051906020012090505f610e01826114b9565b905060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610e4e85836114ec90919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff1614610ea4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9b90612701565b60405180910390fd5b5f610eae86611516565b90505f8782610ebd919061237e565b905080341015610f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef99061250c565b60405180910390fd5b610f0c338661143a565b84600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610f5891906123bf565b9250508190555080341115610fb7573373ffffffffffffffffffffffffffffffffffffffff166108fc8234610f8d919061234b565b90811502906040515f60405180830381858888f19350505050158015610fb5573d5f803e3d5ffd5b505b5050505050505050565b60085481565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b6110516110cd565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036110c1575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016110b89190611ead565b60405180910390fd5b6110ca816112ef565b50565b6110d5611154565b73ffffffffffffffffffffffffffffffffffffffff166110f36108a0565b73ffffffffffffffffffffffffffffffffffffffff161461115257611116611154565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016111499190611ead565b60405180910390fd5b565b5f33905090565b6111688383836001611588565b505050565b5f6111788484610fc7565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146111f957818110156111ea578281836040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526004016111e19392919061271f565b60405180910390fd5b6111f884848484035f611588565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361126f575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016112669190611ead565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036112df575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016112d69190611ead565b60405180910390fd5b6112ea838383611757565b505050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6113bb6107c6565b600a6113c79190612883565b826113d2919061237e565b9050600654816113e061073c565b6113ea91906123bf565b111561142b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611422906124a4565b60405180910390fd5b611435838261143a565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036114aa575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016114a19190611ead565b60405180910390fd5b6114b55f8383611757565b5050565b5f7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f5281601c52603c5f209050919050565b5f805f806114fa8686611970565b92509250925061150a82826119c5565b82935050505092915050565b5f806001831015801561152b57506151cb8311155b1561155d576151cb605084611540919061237e565b61154a91906128fa565b600a61155691906123bf565b9050611562565b605a90505b606481655af3107a4000611576919061237e565b61158091906128fa565b915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036115f8575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016115ef9190611ead565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611668575f6040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161165f9190611ead565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015611751578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516117489190611e01565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036117a7578060025f82825461179b91906123bf565b92505081905550611875565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611830578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016118279392919061271f565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118bc578060025f8282540392505081905550611906565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516119639190611e01565b60405180910390a3505050565b5f805f60418451036119b0575f805f602087015192506040870151915060608701515f1a90506119a288828585611b27565b9550955095505050506119be565b5f600285515f1b9250925092505b9250925092565b5f60038111156119d8576119d761292a565b5b8260038111156119eb576119ea61292a565b5b0315611b235760016003811115611a0557611a0461292a565b5b826003811115611a1857611a1761292a565b5b03611a4f576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115611a6357611a6261292a565b5b826003811115611a7657611a7561292a565b5b03611aba57805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401611ab19190611e01565b60405180910390fd5b600380811115611acd57611acc61292a565b5b826003811115611ae057611adf61292a565b5b03611b2257806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401611b19919061296f565b60405180910390fd5b5b5050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115611b63575f600385925092509250611c04565b5f6001888888886040515f8152602001604052604051611b869493929190612988565b6020604051602081039080840390855afa158015611ba6573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611bf7575f60015f801b93509350935050611c04565b805f805f1b935093509350505b9450945094915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611c4882611c1f565b9050919050565b611c5881611c3e565b8114611c62575f80fd5b50565b5f81359050611c7381611c4f565b92915050565b5f60208284031215611c8e57611c8d611c17565b5b5f611c9b84828501611c65565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611cdb578082015181840152602081019050611cc0565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611d0082611ca4565b611d0a8185611cae565b9350611d1a818560208601611cbe565b611d2381611ce6565b840191505092915050565b5f6020820190508181035f830152611d468184611cf6565b905092915050565b5f819050919050565b611d6081611d4e565b8114611d6a575f80fd5b50565b5f81359050611d7b81611d57565b92915050565b5f8060408385031215611d9757611d96611c17565b5b5f611da485828601611c65565b9250506020611db585828601611d6d565b9150509250929050565b5f8115159050919050565b611dd381611dbf565b82525050565b5f602082019050611dec5f830184611dca565b92915050565b611dfb81611d4e565b82525050565b5f602082019050611e145f830184611df2565b92915050565b5f805f60608486031215611e3157611e30611c17565b5b5f611e3e86828701611c65565b9350506020611e4f86828701611c65565b9250506040611e6086828701611d6d565b9150509250925092565b5f60ff82169050919050565b611e7f81611e6a565b82525050565b5f602082019050611e985f830184611e76565b92915050565b611ea781611c3e565b82525050565b5f602082019050611ec05f830184611e9e565b92915050565b5f60208284031215611edb57611eda611c17565b5b5f611ee884828501611d6d565b91505092915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b611f2b82611ce6565b810181811067ffffffffffffffff82111715611f4a57611f49611ef5565b5b80604052505050565b5f611f5c611c0e565b9050611f688282611f22565b919050565b5f67ffffffffffffffff821115611f8757611f86611ef5565b5b602082029050602081019050919050565b5f80fd5b5f611fae611fa984611f6d565b611f53565b90508083825260208201905060208402830185811115611fd157611fd0611f98565b5b835b81811015611ffa5780611fe68882611c65565b845260208401935050602081019050611fd3565b5050509392505050565b5f82601f83011261201857612017611ef1565b5b8135612028848260208601611f9c565b91505092915050565b5f67ffffffffffffffff82111561204b5761204a611ef5565b5b602082029050602081019050919050565b5f61206e61206984612031565b611f53565b9050808382526020820190506020840283018581111561209157612090611f98565b5b835b818110156120ba57806120a68882611d6d565b845260208401935050602081019050612093565b5050509392505050565b5f82601f8301126120d8576120d7611ef1565b5b81356120e884826020860161205c565b91505092915050565b5f806040838503121561210757612106611c17565b5b5f83013567ffffffffffffffff81111561212457612123611c1b565b5b61213085828601612004565b925050602083013567ffffffffffffffff81111561215157612150611c1b565b5b61215d858286016120c4565b9150509250929050565b5f80fd5b5f67ffffffffffffffff82111561218557612184611ef5565b5b61218e82611ce6565b9050602081019050919050565b828183375f83830152505050565b5f6121bb6121b68461216b565b611f53565b9050828152602081018484840111156121d7576121d6612167565b5b6121e284828561219b565b509392505050565b5f82601f8301126121fe576121fd611ef1565b5b813561220e8482602086016121a9565b91505092915050565b5f805f6060848603121561222e5761222d611c17565b5b5f61223b86828701611d6d565b935050602061224c86828701611d6d565b925050604084013567ffffffffffffffff81111561226d5761226c611c1b565b5b612279868287016121ea565b9150509250925092565b5f806040838503121561229957612298611c17565b5b5f6122a685828601611c65565b92505060206122b785828601611c65565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061230557607f821691505b602082108103612318576123176122c1565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61235582611d4e565b915061236083611d4e565b92508282039050818111156123785761237761231e565b5b92915050565b5f61238882611d4e565b915061239383611d4e565b92508282026123a181611d4e565b915082820484148315176123b8576123b761231e565b5b5092915050565b5f6123c982611d4e565b91506123d483611d4e565b92508282019050808211156123ec576123eb61231e565b5b92915050565b7f4d696e74206c696d6974206578636565646564000000000000000000000000005f82015250565b5f612426601383611cae565b9150612431826123f2565b602082019050919050565b5f6020820190508181035f8301526124538161241a565b9050919050565b7f4d617820737570706c79206578636565646564000000000000000000000000005f82015250565b5f61248e601383611cae565b91506124998261245a565b602082019050919050565b5f6020820190508181035f8301526124bb81612482565b9050919050565b7f496e73756666696369656e74204554482073656e7400000000000000000000005f82015250565b5f6124f6601583611cae565b9150612501826124c2565b602082019050919050565b5f6020820190508181035f830152612523816124ea565b9050919050565b7f4d69736d617463686564206172726179206c656e6774687300000000000000005f82015250565b5f61255e601883611cae565b91506125698261252a565b602082019050919050565b5f6020820190508181035f83015261258b81612552565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f464944206d757374206265206120706f73697469766520696e746567657200005f82015250565b5f6125f3601e83611cae565b91506125fe826125bf565b602082019050919050565b5f6020820190508181035f830152612620816125e7565b9050919050565b5f8160601b9050919050565b5f61263d82612627565b9050919050565b5f61264e82612633565b9050919050565b61266661266182611c3e565b612644565b82525050565b5f819050919050565b61268661268182611d4e565b61266c565b82525050565b5f6126978285612655565b6014820191506126a78284612675565b6020820191508190509392505050565b7f496e76616c6964207369676e61747572650000000000000000000000000000005f82015250565b5f6126eb601183611cae565b91506126f6826126b7565b602082019050919050565b5f6020820190508181035f830152612718816126df565b9050919050565b5f6060820190506127325f830186611e9e565b61273f6020830185611df2565b61274c6040830184611df2565b949350505050565b5f8160011c9050919050565b5f808291508390505b60018511156127a9578086048111156127855761278461231e565b5b60018516156127945780820291505b80810290506127a285612754565b9450612769565b94509492505050565b5f826127c1576001905061287c565b816127ce575f905061287c565b81600181146127e457600281146127ee5761281d565b600191505061287c565b60ff841115612800576127ff61231e565b5b8360020a9150848211156128175761281661231e565b5b5061287c565b5060208310610133831016604e8410600b84101617156128525782820a90508381111561284d5761284c61231e565b5b61287c565b61285f8484846001612760565b925090508184048111156128765761287561231e565b5b81810290505b9392505050565b5f61288d82611d4e565b915061289883611e6a565b92506128c57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846127b2565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61290482611d4e565b915061290f83611d4e565b92508261291f5761291e6128cd565b5b828204905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f819050919050565b61296981612957565b82525050565b5f6020820190506129825f830184612960565b92915050565b5f60808201905061299b5f830187612960565b6129a86020830186611e76565b6129b56040830185612960565b6129c26060830184612960565b9594505050505056fea2646970667358221220c42118c3525263de6d908f7676b7de49237a1d9bfd251112afe1cb1786e03b7e64736f6c63430008170033

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

000000000000000000000000dd94873dd3d62233ab263d038091c84fcd247a4c

-----Decoded View---------------
Arg [0] : initialOwner (address): 0xdD94873Dd3d62233AB263D038091c84FcD247a4c

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000dd94873dd3d62233ab263d038091c84fcd247a4c


Deployed Bytecode Sourcemap

57692:4645:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62216:118;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;48298:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;50591:190;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49400:99;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61136:140;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;51359:249;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49251:84;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;57771:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;57951:59;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;57803:35;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;58019:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;58160:48;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49562:118;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41911:103;;;;;;;;;;;;;:::i;:::-;;58054:97;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61284:101;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;41236:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;48508:95;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;58533:776;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62084:124;;;;;;;;;;;;;:::i;:::-;;49885:182;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;57845:63;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61393:367;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;59317:1259;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;57915:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;50130:142;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;42169:220;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62216:118;41122:13;:11;:13::i;:::-;62312:14:::1;62296:13;;:30;;;;;;;;;;;;;;;;;;62216:118:::0;:::o;48298:91::-;48343:13;48376:5;48369:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48298:91;:::o;50591:190::-;50664:4;50681:13;50697:12;:10;:12::i;:::-;50681:28;;50720:31;50729:5;50736:7;50745:5;50720:8;:31::i;:::-;50769:4;50762:11;;;50591:190;;;;:::o;49400:99::-;49452:7;49479:12;;49472:19;;49400:99;:::o;61136:140::-;61199:7;61249:13;:19;61263:4;61249:19;;;;;;;;;;;;;;;;61226:20;;:42;;;;:::i;:::-;61219:49;;61136:140;;;:::o;51359:249::-;51446:4;51463:15;51481:12;:10;:12::i;:::-;51463:30;;51504:37;51520:4;51526:7;51535:5;51504:15;:37::i;:::-;51552:26;51562:4;51568:2;51572:5;51552:9;:26::i;:::-;51596:4;51589:11;;;51359:249;;;;;:::o;49251:84::-;49300:5;49325:2;49318:9;;49251:84;:::o;57771:25::-;;;;:::o;57951:59::-;58005:5;57951:59;:::o;57803:35::-;;;;:::o;58019:28::-;;;;;;;;;;;;;:::o;58160:48::-;;;;;;;;;;;;;;;;;:::o;49562:118::-;49627:7;49654:9;:18;49664:7;49654:18;;;;;;;;;;;;;;;;49647:25;;49562:118;;;:::o;41911:103::-;41122:13;:11;:13::i;:::-;41976:30:::1;42003:1;41976:18;:30::i;:::-;41911:103::o:0;58054:97::-;58109:42;58054:97;:::o;61284:101::-;41122:13;:11;:13::i;:::-;61357:20:::1;61366:2;61370:6;61357:8;:20::i;:::-;61284:101:::0;;:::o;41236:87::-;41282:7;41309:6;;;;;;;;;;;41302:13;;41236:87;:::o;48508:95::-;48555:13;48588:7;48581:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48508:95;:::o;58533:776::-;58599:20;58641:14;;58622:16;:33;;;;:::i;:::-;58599:56;;58732:20;;58716:12;58688:13;:25;58702:10;58688:25;;;;;;;;;;;;;;;;:40;;;;:::i;:::-;:64;;58666:133;;;;;;;;;;;;:::i;:::-;;;;;;;;;58864:10;;58848:12;58832:13;:11;:13::i;:::-;:28;;;;:::i;:::-;:42;;58810:111;;;;;;;;;;;;:::i;:::-;;;;;;;;;58934:23;57896:12;58960:16;:43;;;;:::i;:::-;58934:69;;59035:15;59022:9;:28;;59014:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;59089:31;59095:10;59107:12;59089:5;:31::i;:::-;59160:12;59131:13;:25;59145:10;59131:25;;;;;;;;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;59201:15;59189:9;:27;59185:117;;;59241:10;59233:28;;:57;59274:15;59262:9;:27;;;;:::i;:::-;59233:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59185:117;58588:721;;58533:776;:::o;62084:124::-;41122:13;:11;:13::i;:::-;58109:42:::1;62140:37;;:60;62178:21;62140:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;62084:124::o:0;49885:182::-;49954:4;49971:13;49987:12;:10;:12::i;:::-;49971:28;;50010:27;50020:5;50027:2;50031:5;50010:9;:27::i;:::-;50055:4;50048:11;;;49885:182;;;;:::o;57845:63::-;57896:12;57845:63;:::o;61393:367::-;41122:13;:11;:13::i;:::-;61564:7:::1;:14;61543:10;:17;:35;61521:109;;;;;;;;;;;;:::i;:::-;;;;;;;;;61648:9;61643:110;61667:10;:17;61663:1;:21;61643:110;;;61706:35;61715:10;61726:1;61715:13;;;;;;;;:::i;:::-;;;;;;;;61730:7;61738:1;61730:10;;;;;;;;:::i;:::-;;;;;;;;61706:8;:35::i;:::-;61686:3;;;;;;;61643:110;;;;61393:367:::0;;:::o;59317:1259::-;59491:1;59477:11;:15;59469:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;59538:20;59580:14;;59561:16;:33;;;;:::i;:::-;59538:56;;59671:20;;59655:12;59627:13;:25;59641:10;59627:25;;;;;;;;;;;;;;;;:40;;;;:::i;:::-;:64;;59605:133;;;;;;;;;;;;:::i;:::-;;;;;;;;;59803:10;;59787:12;59771:13;:11;:13::i;:::-;:28;;;;:::i;:::-;:42;;59749:111;;;;;;;;;;;;:::i;:::-;;;;;;;;;59873:15;59918:10;59930:11;59901:41;;;;;;;;;:::i;:::-;;;;;;;;;;;;;59891:52;;;;;;59873:70;;59954:25;59982:72;60036:7;59982:39;:72::i;:::-;59954:100;;60127:13;;;;;;;;;;;60087:53;;:36;60113:9;60087:17;:25;;:36;;;;:::i;:::-;:53;;;60065:120;;;;;;;;;;;;:::i;:::-;;;;;;;;;60198:17;60218:31;60237:11;60218:18;:31::i;:::-;60198:51;;60260:12;60287:16;60275:9;:28;;;;:::i;:::-;60260:43;;60335:4;60322:9;:17;;60314:51;;;;;;;;;;;;:::i;:::-;;;;;;;;;60378:31;60384:10;60396:12;60378:5;:31::i;:::-;60449:12;60420:13;:25;60434:10;60420:25;;;;;;;;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;60490:4;60478:9;:16;60474:95;;;60519:10;60511:28;;:46;60552:4;60540:9;:16;;;;:::i;:::-;60511:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60474:95;59458:1118;;;;;59317:1259;;;:::o;57915:29::-;;;;:::o;50130:142::-;50210:7;50237:11;:18;50249:5;50237:18;;;;;;;;;;;;;;;:27;50256:7;50237:27;;;;;;;;;;;;;;;;50230:34;;50130:142;;;;:::o;42169:220::-;41122:13;:11;:13::i;:::-;42274:1:::1;42254:22;;:8;:22;;::::0;42250:93:::1;;42328:1;42300:31;;;;;;;;;;;:::i;:::-;;;;;;;;42250:93;42353:28;42372:8;42353:18;:28::i;:::-;42169:220:::0;:::o;41401:166::-;41472:12;:10;:12::i;:::-;41461:23;;:7;:5;:7::i;:::-;:23;;;41457:103;;41535:12;:10;:12::i;:::-;41508:40;;;;;;;;;;;:::i;:::-;;;;;;;;41457:103;41401:166::o;39245:98::-;39298:7;39325:10;39318:17;;39245:98;:::o;55418:130::-;55503:37;55512:5;55519:7;55528:5;55535:4;55503:8;:37::i;:::-;55418:130;;;:::o;57134:487::-;57234:24;57261:25;57271:5;57278:7;57261:9;:25::i;:::-;57234:52;;57321:17;57301:16;:37;57297:317;;57378:5;57359:16;:24;57355:132;;;57438:7;57447:16;57465:5;57411:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;57355:132;57530:57;57539:5;57546:7;57574:5;57555:16;:24;57581:5;57530:8;:57::i;:::-;57297:317;57223:398;57134:487;;;:::o;51993:308::-;52093:1;52077:18;;:4;:18;;;52073:88;;52146:1;52119:30;;;;;;;;;;;:::i;:::-;;;;;;;;52073:88;52189:1;52175:16;;:2;:16;;;52171:88;;52244:1;52215:32;;;;;;;;;;;:::i;:::-;;;;;;;;52171:88;52269:24;52277:4;52283:2;52287:5;52269:7;:24::i;:::-;51993:308;;;:::o;42549:191::-;42623:16;42642:6;;;;;;;;;;;42623:25;;42668:8;42659:6;;:17;;;;;;;;;;;;;;;;;;42723:8;42692:40;;42713:8;42692:40;;;;;;;;;;;;42612:128;42549:191;:::o;61768:308::-;61841:26;61883:10;:8;:10::i;:::-;61879:2;:14;;;;:::i;:::-;61870:6;:23;;;;:::i;:::-;61841:52;;61964:10;;61942:18;61926:13;:11;:13::i;:::-;:34;;;;:::i;:::-;:48;;61904:117;;;;;;;;;;;;:::i;:::-;;;;;;;;;62032:36;62038:9;62049:18;62032:5;:36::i;:::-;61830:246;61768:308;;:::o;54113:213::-;54203:1;54184:21;;:7;:21;;;54180:93;;54258:1;54229:32;;;;;;;;;;;:::i;:::-;;;;;;;;54180:93;54283:35;54299:1;54303:7;54312:5;54283:7;:35::i;:::-;54113:213;;:::o;21285:467::-;21361:14;21469:34;21463:4;21456:48;21572:11;21566:4;21559:25;21665:4;21659;21649:21;21639:31;;21285:467;;;:::o;27703:259::-;27781:7;27802:17;27821:18;27841:16;27861:27;27872:4;27878:9;27861:10;:27::i;:::-;27801:87;;;;;;27899:28;27911:5;27918:8;27899:11;:28::i;:::-;27945:9;27938:16;;;;;27703:259;;;;:::o;60584:544::-;60683:7;60708:19;60759:1;60744:11;:16;;:62;;;;;58005:5;60764:11;:42;;60744:62;60740:315;;;58005:5;60961:2;60947:11;:16;;;;:::i;:::-;60946:48;;;;:::i;:::-;60941:2;:53;;;;:::i;:::-;60927:67;;60740:315;;;61041:2;61027:16;;60740:315;61117:3;61102:11;57896:12;61075:38;;;;:::i;:::-;61074:46;;;;:::i;:::-;61067:53;;;60584:544;;;:::o;56399:443::-;56529:1;56512:19;;:5;:19;;;56508:91;;56584:1;56555:32;;;;;;;;;;;:::i;:::-;;;;;;;;56508:91;56632:1;56613:21;;:7;:21;;;56609:92;;56686:1;56658:31;;;;;;;;;;;:::i;:::-;;;;;;;;56609:92;56741:5;56711:11;:18;56723:5;56711:18;;;;;;;;;;;;;;;:27;56730:7;56711:27;;;;;;;;;;;;;;;:35;;;;56761:9;56757:78;;;56808:7;56792:31;;56801:5;56792:31;;;56817:5;56792:31;;;;;;:::i;:::-;;;;;;;;56757:78;56399:443;;;;:::o;52625:1135::-;52731:1;52715:18;;:4;:18;;;52711:552;;52869:5;52853:12;;:21;;;;;;;:::i;:::-;;;;;;;;52711:552;;;52907:19;52929:9;:15;52939:4;52929:15;;;;;;;;;;;;;;;;52907:37;;52977:5;52963:11;:19;52959:117;;;53035:4;53041:11;53054:5;53010:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;52959:117;53231:5;53217:11;:19;53199:9;:15;53209:4;53199:15;;;;;;;;;;;;;;;:37;;;;52892:371;52711:552;53293:1;53279:16;;:2;:16;;;53275:435;;53461:5;53445:12;;:21;;;;;;;;;;;53275:435;;;53678:5;53661:9;:13;53671:2;53661:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;53275:435;53742:2;53727:25;;53736:4;53727:25;;;53746:5;53727:25;;;;;;:::i;:::-;;;;;;;;52625:1135;;;:::o;26097:783::-;26178:7;26187:12;26201:7;26245:2;26225:9;:16;:22;26221:652;;26264:9;26288;26312:7;26569:4;26558:9;26554:20;26548:27;26543:32;;26619:4;26608:9;26604:20;26598:27;26593:32;;26677:4;26666:9;26662:20;26656:27;26653:1;26648:36;26643:41;;26720:25;26731:4;26737:1;26740;26743;26720:10;:25::i;:::-;26713:32;;;;;;;;;;;26221:652;26794:1;26798:35;26843:9;:16;26835:25;;26778:83;;;;;;26097:783;;;;;;:::o;31271:542::-;31367:20;31358:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;31354:452;31404:7;31354:452;31465:29;31456:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;31452:354;;31518:23;;;;;;;;;;;;;;31452:354;31572:35;31563:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;31559:247;;31667:8;31659:17;;31631:46;;;;;;;;;;;:::i;:::-;;;;;;;;31559:247;31708:30;31699:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;31695:111;;31785:8;31762:32;;;;;;;;;;;:::i;:::-;;;;;;;;31695:111;31271:542;;;:::o;29174:1556::-;29305:7;29314:12;29328:7;30248:66;30243:1;30235:10;;:79;30231:166;;;30347:1;30351:30;30383:1;30331:54;;;;;;;;30231:166;30494:14;30511:24;30521:4;30527:1;30530;30533;30511:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30494:41;;30568:1;30550:20;;:6;:20;;;30546:115;;30603:1;30607:29;30646:1;30638:10;;30587:62;;;;;;;;;30546:115;30681:6;30689:20;30719:1;30711:10;;30673:49;;;;;;;29174:1556;;;;;;;;;:::o;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:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:139::-;742:5;780:6;767:20;758:29;;796:33;823:5;796:33;:::i;:::-;696:139;;;;:::o;841:329::-;900:6;949:2;937:9;928:7;924:23;920:32;917:119;;;955:79;;:::i;:::-;917:119;1075:1;1100:53;1145:7;1136:6;1125:9;1121:22;1100:53;:::i;:::-;1090:63;;1046:117;841:329;;;;:::o;1176:99::-;1228:6;1262:5;1256:12;1246:22;;1176:99;;;:::o;1281:169::-;1365:11;1399:6;1394:3;1387:19;1439:4;1434:3;1430:14;1415:29;;1281:169;;;;:::o;1456:246::-;1537:1;1547:113;1561:6;1558:1;1555:13;1547:113;;;1646:1;1641:3;1637:11;1631:18;1627:1;1622:3;1618:11;1611:39;1583:2;1580:1;1576:10;1571:15;;1547:113;;;1694:1;1685:6;1680:3;1676:16;1669:27;1518:184;1456:246;;;:::o;1708:102::-;1749:6;1800:2;1796:7;1791:2;1784:5;1780:14;1776:28;1766:38;;1708:102;;;:::o;1816:377::-;1904:3;1932:39;1965:5;1932:39;:::i;:::-;1987:71;2051:6;2046:3;1987:71;:::i;:::-;1980:78;;2067:65;2125:6;2120:3;2113:4;2106:5;2102:16;2067:65;:::i;:::-;2157:29;2179:6;2157:29;:::i;:::-;2152:3;2148:39;2141:46;;1908:285;1816:377;;;;:::o;2199:313::-;2312:4;2350:2;2339:9;2335:18;2327:26;;2399:9;2393:4;2389:20;2385:1;2374:9;2370:17;2363:47;2427:78;2500:4;2491:6;2427:78;:::i;:::-;2419:86;;2199:313;;;;:::o;2518:77::-;2555:7;2584:5;2573:16;;2518:77;;;:::o;2601:122::-;2674:24;2692:5;2674:24;:::i;:::-;2667:5;2664:35;2654:63;;2713:1;2710;2703:12;2654:63;2601:122;:::o;2729:139::-;2775:5;2813:6;2800:20;2791:29;;2829:33;2856:5;2829:33;:::i;:::-;2729:139;;;;:::o;2874:474::-;2942:6;2950;2999:2;2987:9;2978:7;2974:23;2970:32;2967:119;;;3005:79;;:::i;:::-;2967:119;3125:1;3150:53;3195:7;3186:6;3175:9;3171:22;3150:53;:::i;:::-;3140:63;;3096:117;3252:2;3278:53;3323:7;3314:6;3303:9;3299:22;3278:53;:::i;:::-;3268:63;;3223:118;2874:474;;;;;:::o;3354:90::-;3388:7;3431:5;3424:13;3417:21;3406:32;;3354:90;;;:::o;3450:109::-;3531:21;3546:5;3531:21;:::i;:::-;3526:3;3519:34;3450:109;;:::o;3565:210::-;3652:4;3690:2;3679:9;3675:18;3667:26;;3703:65;3765:1;3754:9;3750:17;3741:6;3703:65;:::i;:::-;3565:210;;;;:::o;3781:118::-;3868:24;3886:5;3868:24;:::i;:::-;3863:3;3856:37;3781:118;;:::o;3905:222::-;3998:4;4036:2;4025:9;4021:18;4013:26;;4049:71;4117:1;4106:9;4102:17;4093:6;4049:71;:::i;:::-;3905:222;;;;:::o;4133:619::-;4210:6;4218;4226;4275:2;4263:9;4254:7;4250:23;4246:32;4243:119;;;4281:79;;:::i;:::-;4243:119;4401:1;4426:53;4471:7;4462:6;4451:9;4447:22;4426:53;:::i;:::-;4416:63;;4372:117;4528:2;4554:53;4599:7;4590:6;4579:9;4575:22;4554:53;:::i;:::-;4544:63;;4499:118;4656:2;4682:53;4727:7;4718:6;4707:9;4703:22;4682:53;:::i;:::-;4672:63;;4627:118;4133:619;;;;;:::o;4758:86::-;4793:7;4833:4;4826:5;4822:16;4811:27;;4758:86;;;:::o;4850:112::-;4933:22;4949:5;4933:22;:::i;:::-;4928:3;4921:35;4850:112;;:::o;4968:214::-;5057:4;5095:2;5084:9;5080:18;5072:26;;5108:67;5172:1;5161:9;5157:17;5148:6;5108:67;:::i;:::-;4968:214;;;;:::o;5188:118::-;5275:24;5293:5;5275:24;:::i;:::-;5270:3;5263:37;5188:118;;:::o;5312:222::-;5405:4;5443:2;5432:9;5428:18;5420:26;;5456:71;5524:1;5513:9;5509:17;5500:6;5456:71;:::i;:::-;5312:222;;;;:::o;5540:329::-;5599:6;5648:2;5636:9;5627:7;5623:23;5619:32;5616:119;;;5654:79;;:::i;:::-;5616:119;5774:1;5799:53;5844:7;5835:6;5824:9;5820:22;5799:53;:::i;:::-;5789:63;;5745:117;5540:329;;;;:::o;5875:117::-;5984:1;5981;5974:12;5998:180;6046:77;6043:1;6036:88;6143:4;6140:1;6133:15;6167:4;6164:1;6157:15;6184:281;6267:27;6289:4;6267:27;:::i;:::-;6259:6;6255:40;6397:6;6385:10;6382:22;6361:18;6349:10;6346:34;6343:62;6340:88;;;6408:18;;:::i;:::-;6340:88;6448:10;6444:2;6437:22;6227:238;6184:281;;:::o;6471:129::-;6505:6;6532:20;;:::i;:::-;6522:30;;6561:33;6589:4;6581:6;6561:33;:::i;:::-;6471:129;;;:::o;6606:311::-;6683:4;6773:18;6765:6;6762:30;6759:56;;;6795:18;;:::i;:::-;6759:56;6845:4;6837:6;6833:17;6825:25;;6905:4;6899;6895:15;6887:23;;6606:311;;;:::o;6923:117::-;7032:1;7029;7022:12;7063:710;7159:5;7184:81;7200:64;7257:6;7200:64;:::i;:::-;7184:81;:::i;:::-;7175:90;;7285:5;7314:6;7307:5;7300:21;7348:4;7341:5;7337:16;7330:23;;7401:4;7393:6;7389:17;7381:6;7377:30;7430:3;7422:6;7419:15;7416:122;;;7449:79;;:::i;:::-;7416:122;7564:6;7547:220;7581:6;7576:3;7573:15;7547:220;;;7656:3;7685:37;7718:3;7706:10;7685:37;:::i;:::-;7680:3;7673:50;7752:4;7747:3;7743:14;7736:21;;7623:144;7607:4;7602:3;7598:14;7591:21;;7547:220;;;7551:21;7165:608;;7063:710;;;;;:::o;7796:370::-;7867:5;7916:3;7909:4;7901:6;7897:17;7893:27;7883:122;;7924:79;;:::i;:::-;7883:122;8041:6;8028:20;8066:94;8156:3;8148:6;8141:4;8133:6;8129:17;8066:94;:::i;:::-;8057:103;;7873:293;7796:370;;;;:::o;8172:311::-;8249:4;8339:18;8331:6;8328:30;8325:56;;;8361:18;;:::i;:::-;8325:56;8411:4;8403:6;8399:17;8391:25;;8471:4;8465;8461:15;8453:23;;8172:311;;;:::o;8506:710::-;8602:5;8627:81;8643:64;8700:6;8643:64;:::i;:::-;8627:81;:::i;:::-;8618:90;;8728:5;8757:6;8750:5;8743:21;8791:4;8784:5;8780:16;8773:23;;8844:4;8836:6;8832:17;8824:6;8820:30;8873:3;8865:6;8862:15;8859:122;;;8892:79;;:::i;:::-;8859:122;9007:6;8990:220;9024:6;9019:3;9016:15;8990:220;;;9099:3;9128:37;9161:3;9149:10;9128:37;:::i;:::-;9123:3;9116:50;9195:4;9190:3;9186:14;9179:21;;9066:144;9050:4;9045:3;9041:14;9034:21;;8990:220;;;8994:21;8608:608;;8506:710;;;;;:::o;9239:370::-;9310:5;9359:3;9352:4;9344:6;9340:17;9336:27;9326:122;;9367:79;;:::i;:::-;9326:122;9484:6;9471:20;9509:94;9599:3;9591:6;9584:4;9576:6;9572:17;9509:94;:::i;:::-;9500:103;;9316:293;9239:370;;;;:::o;9615:894::-;9733:6;9741;9790:2;9778:9;9769:7;9765:23;9761:32;9758:119;;;9796:79;;:::i;:::-;9758:119;9944:1;9933:9;9929:17;9916:31;9974:18;9966:6;9963:30;9960:117;;;9996:79;;:::i;:::-;9960:117;10101:78;10171:7;10162:6;10151:9;10147:22;10101:78;:::i;:::-;10091:88;;9887:302;10256:2;10245:9;10241:18;10228:32;10287:18;10279:6;10276:30;10273:117;;;10309:79;;:::i;:::-;10273:117;10414:78;10484:7;10475:6;10464:9;10460:22;10414:78;:::i;:::-;10404:88;;10199:303;9615:894;;;;;:::o;10515:117::-;10624:1;10621;10614:12;10638:307;10699:4;10789:18;10781:6;10778:30;10775:56;;;10811:18;;:::i;:::-;10775:56;10849:29;10871:6;10849:29;:::i;:::-;10841:37;;10933:4;10927;10923:15;10915:23;;10638:307;;;:::o;10951:146::-;11048:6;11043:3;11038;11025:30;11089:1;11080:6;11075:3;11071:16;11064:27;10951:146;;;:::o;11103:423::-;11180:5;11205:65;11221:48;11262:6;11221:48;:::i;:::-;11205:65;:::i;:::-;11196:74;;11293:6;11286:5;11279:21;11331:4;11324:5;11320:16;11369:3;11360:6;11355:3;11351:16;11348:25;11345:112;;;11376:79;;:::i;:::-;11345:112;11466:54;11513:6;11508:3;11503;11466:54;:::i;:::-;11186:340;11103:423;;;;;:::o;11545:338::-;11600:5;11649:3;11642:4;11634:6;11630:17;11626:27;11616:122;;11657:79;;:::i;:::-;11616:122;11774:6;11761:20;11799:78;11873:3;11865:6;11858:4;11850:6;11846:17;11799:78;:::i;:::-;11790:87;;11606:277;11545:338;;;;:::o;11889:797::-;11975:6;11983;11991;12040:2;12028:9;12019:7;12015:23;12011:32;12008:119;;;12046:79;;:::i;:::-;12008:119;12166:1;12191:53;12236:7;12227:6;12216:9;12212:22;12191:53;:::i;:::-;12181:63;;12137:117;12293:2;12319:53;12364:7;12355:6;12344:9;12340:22;12319:53;:::i;:::-;12309:63;;12264:118;12449:2;12438:9;12434:18;12421:32;12480:18;12472:6;12469:30;12466:117;;;12502:79;;:::i;:::-;12466:117;12607:62;12661:7;12652:6;12641:9;12637:22;12607:62;:::i;:::-;12597:72;;12392:287;11889:797;;;;;:::o;12692:474::-;12760:6;12768;12817:2;12805:9;12796:7;12792:23;12788:32;12785:119;;;12823:79;;:::i;:::-;12785:119;12943:1;12968:53;13013:7;13004:6;12993:9;12989:22;12968:53;:::i;:::-;12958:63;;12914:117;13070:2;13096:53;13141:7;13132:6;13121:9;13117:22;13096:53;:::i;:::-;13086:63;;13041:118;12692:474;;;;;:::o;13172:180::-;13220:77;13217:1;13210:88;13317:4;13314:1;13307:15;13341:4;13338:1;13331:15;13358:320;13402:6;13439:1;13433:4;13429:12;13419:22;;13486:1;13480:4;13476:12;13507:18;13497:81;;13563:4;13555:6;13551:17;13541:27;;13497:81;13625:2;13617:6;13614:14;13594:18;13591:38;13588:84;;13644:18;;:::i;:::-;13588:84;13409:269;13358:320;;;:::o;13684:180::-;13732:77;13729:1;13722:88;13829:4;13826:1;13819:15;13853:4;13850:1;13843:15;13870:194;13910:4;13930:20;13948:1;13930:20;:::i;:::-;13925:25;;13964:20;13982:1;13964:20;:::i;:::-;13959:25;;14008:1;14005;14001:9;13993:17;;14032:1;14026:4;14023:11;14020:37;;;14037:18;;:::i;:::-;14020:37;13870:194;;;;:::o;14070:410::-;14110:7;14133:20;14151:1;14133:20;:::i;:::-;14128:25;;14167:20;14185:1;14167:20;:::i;:::-;14162:25;;14222:1;14219;14215:9;14244:30;14262:11;14244:30;:::i;:::-;14233:41;;14423:1;14414:7;14410:15;14407:1;14404:22;14384:1;14377:9;14357:83;14334:139;;14453:18;;:::i;:::-;14334:139;14118:362;14070:410;;;;:::o;14486:191::-;14526:3;14545:20;14563:1;14545:20;:::i;:::-;14540:25;;14579:20;14597:1;14579:20;:::i;:::-;14574:25;;14622:1;14619;14615:9;14608:16;;14643:3;14640:1;14637:10;14634:36;;;14650:18;;:::i;:::-;14634:36;14486:191;;;;:::o;14683:169::-;14823:21;14819:1;14811:6;14807:14;14800:45;14683:169;:::o;14858:366::-;15000:3;15021:67;15085:2;15080:3;15021:67;:::i;:::-;15014:74;;15097:93;15186:3;15097:93;:::i;:::-;15215:2;15210:3;15206:12;15199:19;;14858:366;;;:::o;15230:419::-;15396:4;15434:2;15423:9;15419:18;15411:26;;15483:9;15477:4;15473:20;15469:1;15458:9;15454:17;15447:47;15511:131;15637:4;15511:131;:::i;:::-;15503:139;;15230:419;;;:::o;15655:169::-;15795:21;15791:1;15783:6;15779:14;15772:45;15655:169;:::o;15830:366::-;15972:3;15993:67;16057:2;16052:3;15993:67;:::i;:::-;15986:74;;16069:93;16158:3;16069:93;:::i;:::-;16187:2;16182:3;16178:12;16171:19;;15830:366;;;:::o;16202:419::-;16368:4;16406:2;16395:9;16391:18;16383:26;;16455:9;16449:4;16445:20;16441:1;16430:9;16426:17;16419:47;16483:131;16609:4;16483:131;:::i;:::-;16475:139;;16202:419;;;:::o;16627:171::-;16767:23;16763:1;16755:6;16751:14;16744:47;16627:171;:::o;16804:366::-;16946:3;16967:67;17031:2;17026:3;16967:67;:::i;:::-;16960:74;;17043:93;17132:3;17043:93;:::i;:::-;17161:2;17156:3;17152:12;17145:19;;16804:366;;;:::o;17176:419::-;17342:4;17380:2;17369:9;17365:18;17357:26;;17429:9;17423:4;17419:20;17415:1;17404:9;17400:17;17393:47;17457:131;17583:4;17457:131;:::i;:::-;17449:139;;17176:419;;;:::o;17601:174::-;17741:26;17737:1;17729:6;17725:14;17718:50;17601:174;:::o;17781:366::-;17923:3;17944:67;18008:2;18003:3;17944:67;:::i;:::-;17937:74;;18020:93;18109:3;18020:93;:::i;:::-;18138:2;18133:3;18129:12;18122:19;;17781:366;;;:::o;18153:419::-;18319:4;18357:2;18346:9;18342:18;18334:26;;18406:9;18400:4;18396:20;18392:1;18381:9;18377:17;18370:47;18434:131;18560:4;18434:131;:::i;:::-;18426:139;;18153:419;;;:::o;18578:180::-;18626:77;18623:1;18616:88;18723:4;18720:1;18713:15;18747:4;18744:1;18737:15;18764:180;18904:32;18900:1;18892:6;18888:14;18881:56;18764:180;:::o;18950:366::-;19092:3;19113:67;19177:2;19172:3;19113:67;:::i;:::-;19106:74;;19189:93;19278:3;19189:93;:::i;:::-;19307:2;19302:3;19298:12;19291:19;;18950:366;;;:::o;19322:419::-;19488:4;19526:2;19515:9;19511:18;19503:26;;19575:9;19569:4;19565:20;19561:1;19550:9;19546:17;19539:47;19603:131;19729:4;19603:131;:::i;:::-;19595:139;;19322:419;;;:::o;19747:94::-;19780:8;19828:5;19824:2;19820:14;19799:35;;19747:94;;;:::o;19847:::-;19886:7;19915:20;19929:5;19915:20;:::i;:::-;19904:31;;19847:94;;;:::o;19947:100::-;19986:7;20015:26;20035:5;20015:26;:::i;:::-;20004:37;;19947:100;;;:::o;20053:157::-;20158:45;20178:24;20196:5;20178:24;:::i;:::-;20158:45;:::i;:::-;20153:3;20146:58;20053:157;;:::o;20216:79::-;20255:7;20284:5;20273:16;;20216:79;;;:::o;20301:157::-;20406:45;20426:24;20444:5;20426:24;:::i;:::-;20406:45;:::i;:::-;20401:3;20394:58;20301:157;;:::o;20464:397::-;20604:3;20619:75;20690:3;20681:6;20619:75;:::i;:::-;20719:2;20714:3;20710:12;20703:19;;20732:75;20803:3;20794:6;20732:75;:::i;:::-;20832:2;20827:3;20823:12;20816:19;;20852:3;20845:10;;20464:397;;;;;:::o;20867:167::-;21007:19;21003:1;20995:6;20991:14;20984:43;20867:167;:::o;21040:366::-;21182:3;21203:67;21267:2;21262:3;21203:67;:::i;:::-;21196:74;;21279:93;21368:3;21279:93;:::i;:::-;21397:2;21392:3;21388:12;21381:19;;21040:366;;;:::o;21412:419::-;21578:4;21616:2;21605:9;21601:18;21593:26;;21665:9;21659:4;21655:20;21651:1;21640:9;21636:17;21629:47;21693:131;21819:4;21693:131;:::i;:::-;21685:139;;21412:419;;;:::o;21837:442::-;21986:4;22024:2;22013:9;22009:18;22001:26;;22037:71;22105:1;22094:9;22090:17;22081:6;22037:71;:::i;:::-;22118:72;22186:2;22175:9;22171:18;22162:6;22118:72;:::i;:::-;22200;22268:2;22257:9;22253:18;22244:6;22200:72;:::i;:::-;21837:442;;;;;;:::o;22285:102::-;22327:8;22374:5;22371:1;22367:13;22346:34;;22285:102;;;:::o;22393:848::-;22454:5;22461:4;22485:6;22476:15;;22509:5;22500:14;;22523:712;22544:1;22534:8;22531:15;22523:712;;;22639:4;22634:3;22630:14;22624:4;22621:24;22618:50;;;22648:18;;:::i;:::-;22618:50;22698:1;22688:8;22684:16;22681:451;;;23113:4;23106:5;23102:16;23093:25;;22681:451;23163:4;23157;23153:15;23145:23;;23193:32;23216:8;23193:32;:::i;:::-;23181:44;;22523:712;;;22393:848;;;;;;;:::o;23247:1073::-;23301:5;23492:8;23482:40;;23513:1;23504:10;;23515:5;;23482:40;23541:4;23531:36;;23558:1;23549:10;;23560:5;;23531:36;23627:4;23675:1;23670:27;;;;23711:1;23706:191;;;;23620:277;;23670:27;23688:1;23679:10;;23690:5;;;23706:191;23751:3;23741:8;23738:17;23735:43;;;23758:18;;:::i;:::-;23735:43;23807:8;23804:1;23800:16;23791:25;;23842:3;23835:5;23832:14;23829:40;;;23849:18;;:::i;:::-;23829:40;23882:5;;;23620:277;;24006:2;23996:8;23993:16;23987:3;23981:4;23978:13;23974:36;23956:2;23946:8;23943:16;23938:2;23932:4;23929:12;23925:35;23909:111;23906:246;;;24062:8;24056:4;24052:19;24043:28;;24097:3;24090:5;24087:14;24084:40;;;24104:18;;:::i;:::-;24084:40;24137:5;;23906:246;24177:42;24215:3;24205:8;24199:4;24196:1;24177:42;:::i;:::-;24162:57;;;;24251:4;24246:3;24242:14;24235:5;24232:25;24229:51;;;24260:18;;:::i;:::-;24229:51;24309:4;24302:5;24298:16;24289:25;;23247:1073;;;;;;:::o;24326:281::-;24384:5;24408:23;24426:4;24408:23;:::i;:::-;24400:31;;24452:25;24468:8;24452:25;:::i;:::-;24440:37;;24496:104;24533:66;24523:8;24517:4;24496:104;:::i;:::-;24487:113;;24326:281;;;;:::o;24613:180::-;24661:77;24658:1;24651:88;24758:4;24755:1;24748:15;24782:4;24779:1;24772:15;24799:185;24839:1;24856:20;24874:1;24856:20;:::i;:::-;24851:25;;24890:20;24908:1;24890:20;:::i;:::-;24885:25;;24929:1;24919:35;;24934:18;;:::i;:::-;24919:35;24976:1;24973;24969:9;24964:14;;24799:185;;;;:::o;24990:180::-;25038:77;25035:1;25028:88;25135:4;25132:1;25125:15;25159:4;25156:1;25149:15;25176:77;25213:7;25242:5;25231:16;;25176:77;;;:::o;25259:118::-;25346:24;25364:5;25346:24;:::i;:::-;25341:3;25334:37;25259:118;;:::o;25383:222::-;25476:4;25514:2;25503:9;25499:18;25491:26;;25527:71;25595:1;25584:9;25580:17;25571:6;25527:71;:::i;:::-;25383:222;;;;:::o;25611:545::-;25784:4;25822:3;25811:9;25807:19;25799:27;;25836:71;25904:1;25893:9;25889:17;25880:6;25836:71;:::i;:::-;25917:68;25981:2;25970:9;25966:18;25957:6;25917:68;:::i;:::-;25995:72;26063:2;26052:9;26048:18;26039:6;25995:72;:::i;:::-;26077;26145:2;26134:9;26130:18;26121:6;26077:72;:::i;:::-;25611:545;;;;;;;:::o

Swarm Source

ipfs://c42118c3525263de6d908f7676b7de49237a1d9bfd251112afe1cb1786e03b7e
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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