ETH Price: $2,630.21 (-0.85%)

Token

ETH20 AVATAR (ETH20AVT)
 

Overview

Max Total Supply

0 ETH20AVT

Holders

49

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 ETH20AVT
0xb8865d34c385c30df4495e74b150f81987981d87
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:
ETH20AVATAR

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-09-08
*/

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity 0.8.19;

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

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

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

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

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

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

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

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. 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 {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

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

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

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

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

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

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

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

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // 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.
            require(denominator > prod1, "Math: mulDiv overflow");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @dev Return the log in base 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

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

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

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

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(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) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

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

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

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

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

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

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

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

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

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

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

        return (signer, RecoverError.NoError);
    }

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

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, hash)
            message := keccak256(0x00, 0x3c)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, "\x19\x01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            data := keccak256(ptr, 0x42)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Data with intended validator, created from a
     * `validator` and `data` according to the version 0 of EIP-191.
     *
     * See {recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x00", validator, data));
    }
}

/// The ERC721 standard allows for self-approvals.
/// For performance, this implementation WILL NOT revert for such actions.
/// Please add any checks with overrides if desired.
abstract contract ERC721 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev An account can hold up to 4294967295 tokens.
    uint256 internal constant _MAX_ACCOUNT_BALANCE = 0xffffffff;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Only the token owner or an approved account can manage the token.
    error NotOwnerNorApproved();

    /// @dev The token does not exist.
    error TokenDoesNotExist();

    /// @dev The token already exists.
    error TokenAlreadyExists();

    /// @dev Cannot query the balance for the zero address.
    error BalanceQueryForZeroAddress();

    /// @dev Cannot mint or transfer to the zero address.
    error TransferToZeroAddress();

    /// @dev The token must be owned by `from`.
    error TransferFromIncorrectOwner();

    /// @dev The recipient's balance has overflowed.
    error AccountBalanceOverflow();

    /// @dev Cannot safely transfer to a contract that does not implement
    /// the ERC721Receiver interface.
    error TransferToNonERC721ReceiverImplementer();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when token `id` is transferred from `from` to `to`.
    event Transfer(address indexed from, address indexed to, uint256 indexed id);

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

    /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens.
    event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`.
    uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE =
        0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31;

    // =============================================================
    //                          CONSTRUCTOR
    // =============================================================

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership data slot of `id` is given by:
    /// ```
    ///     mstore(0x00, id)
    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
    ///     let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
    /// ```
    /// Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `extraData`
    ///
    /// The approved address slot is given by: `add(1, ownershipSlot)`.
    ///
    /// See: https://notes.ethereum.org/%40vbuterin/verkle_tree_eip
    ///
    /// The balance slot of `owner` is given by:
    /// ```
    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let balanceSlot := keccak256(0x0c, 0x1c)
    /// ```
    /// Bits Layout:
    /// - [0..31]   `balance`
    /// - [32..225] `aux`
    ///
    /// The `operator` approval slot of `owner` is given by:
    /// ```
    ///     mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))
    ///     mstore(0x00, owner)
    ///     let operatorApprovalSlot := keccak256(0x0c, 0x30)
    /// ```
    uint256 private constant _ERC721_MASTER_SLOT_SEED = 0x7d8825530a5a2e7a << 192;

    /// @dev Pre-shifted and pre-masked constant.
    uint256 private constant _ERC721_MASTER_SLOT_SEED_MASKED = 0x0a5a2e7a00000000;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC721 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

    /// @dev Returns the token collection symbol.
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /// @dev Returns the Uniform Resource Identifier (URI) for token `id`.
    function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
        if (!_exists(tokenId)) revert TokenDoesNotExist();

        string memory baseURI = _baseURI();
        return
            bytes(baseURI).length > 0
                ? string(abi.encodePacked(baseURI, "/", _toHexString(address(this)), "/", _toString(tokenId)))
                : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, it can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERC721                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function ownerOf(uint256 id) public view virtual returns (address result) {
        result = _ownerOf(id);
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(result) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns the number of tokens owned by `owner`.
    ///
    /// Requirements:
    /// - `owner` must not be the zero address.
    function balanceOf(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Revert if the `owner` is the zero address.
            if iszero(owner) {
                mstore(0x00, 0x8f4eb604) // `BalanceQueryForZeroAddress()`.
                revert(0x1c, 0x04)
            }
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            result := and(sload(keccak256(0x0c, 0x1c)), _MAX_ACCOUNT_BALANCE)
        }
    }

    /// @dev Returns the account approved to managed token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function getApproved(uint256 id) public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            if iszero(shr(96, shl(96, sload(ownershipSlot)))) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            result := sload(add(1, ownershipSlot))
        }
    }

    /// @dev Sets `account` as the approved account to manage token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - The caller must be the owner of the token,
    ///   or an approved operator for the token owner.
    ///
    /// Emits a {Approval} event.
    function approve(address account, uint256 id) public payable virtual {
        _approve(msg.sender, account, id);
    }

    /// @dev Returns whether `operator` is approved to manage the tokens of `owner`.
    function isApprovedForAll(address owner, address operator) public view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, operator)
            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x30))
        }
    }

    /// @dev Sets whether `operator` is approved to manage the tokens of the caller.
    ///
    /// Emits a {ApprovalForAll} event.
    function setApprovalForAll(address operator, bool isApproved) public virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Convert to 0 or 1.
            isApproved := iszero(iszero(isApproved))
            // Update the `isApproved` for (`msg.sender`, `operator`).
            mstore(0x1c, operator)
            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x30), isApproved)
            // Emit the {ApprovalForAll} event.
            mstore(0x00, isApproved)
            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), shr(96, shl(96, operator)))
        }
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 id) public payable virtual {
        _beforeTokenTransfer(from, to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            from := and(bitmaskAddress, from)
            to := and(bitmaskAddress, to)
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, caller()))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            let owner := and(bitmaskAddress, ownershipPacked)
            // Revert if `from` is not the owner, or does not exist.
            if iszero(mul(owner, eq(owner, from))) {
                if iszero(owner) {
                    mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`.
                revert(0x1c, 0x04)
            }
            // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
            // Load, check, and update the token approval.
            {
                mstore(0x00, from)
                let approvedAddress := sload(add(1, ownershipSlot))
                // Revert if the caller is not the owner, nor approved.
                if iszero(or(eq(caller(), from), eq(caller(), approvedAddress))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress {
                    sstore(add(1, ownershipSlot), 0)
                }
            }
            // Update with the new owner.
            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))
            // Decrement the balance of `from`.
            {
                let fromBalanceSlot := keccak256(0x0c, 0x1c)
                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))
            }
            // Increment the balance of `to`.
            {
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x1c)
                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
                if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(toBalanceSlot, toBalanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
        _afterTokenTransfer(from, to, id);
    }

    /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`.
    function safeTransferFrom(address from, address to, uint256 id) public payable virtual {
        transferFrom(from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function safeTransferFrom(address from, address to, uint256 id, bytes calldata data) public payable virtual {
        transferFrom(from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @dev Returns true if this contract implements the interface defined by `interfaceId`.
    /// See: https://eips.ethereum.org/EIPS/eip-165
    /// This function call must use less than 30000 gas.
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let s := shr(224, interfaceId)
            // ERC165: 0x01ffc9a7, ERC721: 0x80ac58cd, ERC721Metadata: 0x5b5e139f.
            result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL QUERY FUNCTIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if token `id` exists.
    function _exists(uint256 id) internal view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shl(96, sload(add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Returns the owner of token `id`.
    /// Returns the zero address instead of reverting if the token does not exist.
    function _ownerOf(uint256 id) internal view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shr(96, shl(96, sload(add(id, add(id, keccak256(0x00, 0x20))))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            INTERNAL DATA HITCHHIKING FUNCTIONS             */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the auxiliary data for `owner`.
    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.
    /// Auxiliary data can be set for any address, even if it does not have any tokens.
    function _getAux(address owner) internal view virtual returns (uint224 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            result := shr(32, sload(keccak256(0x0c, 0x1c)))
        }
    }

    /// @dev Set the auxiliary data for `owner` to `value`.
    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.
    /// Auxiliary data can be set for any address, even if it does not have any tokens.
    function _setAux(address owner, uint224 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            let balanceSlot := keccak256(0x0c, 0x1c)
            let packed := sload(balanceSlot)
            sstore(balanceSlot, xor(packed, shl(32, xor(value, shr(32, packed)))))
        }
    }

    /// @dev Returns the extra data for token `id`.
    /// Minting, transferring, burning a token will not change the extra data.
    /// The extra data can be set on a non existent token.
    function _getExtraData(uint256 id) internal view virtual returns (uint96 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shr(160, sload(add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Sets the extra data for token `id` to `value`.
    /// Minting, transferring, burning a token will not change the extra data.
    /// The extra data can be set on a non existent token.
    function _setExtraData(uint256 id, uint96 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let packed := sload(ownershipSlot)
            sstore(ownershipSlot, xor(packed, shl(160, xor(value, shr(160, packed)))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL MINT FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Mints token `id` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must not exist.
    /// - `to` cannot be the zero address.
    ///
    /// Emits a {Transfer} event.
    function _mint(address to, uint256 id) internal virtual {
        _beforeTokenTransfer(address(0), to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            to := shr(96, shl(96, to))
            // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            // Revert if the token already exists.
            if shl(96, ownershipPacked) {
                mstore(0x00, 0xc991cbb1) // `TokenAlreadyExists()`.
                revert(0x1c, 0x04)
            }
            // Update with the owner.
            sstore(ownershipSlot, or(ownershipPacked, to))
            // Increment the balance of the owner.
            {
                mstore(0x00, to)
                let balanceSlot := keccak256(0x0c, 0x1c)
                let balanceSlotPacked := add(sload(balanceSlot), 1)
                if iszero(and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(balanceSlot, balanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id)
        }
        _afterTokenTransfer(address(0), to, id);
    }

    /// @dev Equivalent to `_safeMint(to, id, "")`.
    function _safeMint(address to, uint256 id) internal virtual {
        _safeMint(to, id, "");
    }

    /// @dev Mints token `id` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must not exist.
    /// - `to` cannot be the zero address.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
        _mint(to, id);
        if (_hasCode(to)) _checkOnERC721Received(address(0), to, id, data);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL BURN FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `_burn(address(0), id)`.
    function _burn(uint256 id) internal virtual {
        _burn(address(0), id);
    }

    /// @dev Destroys token `id`, using `by`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function _burn(address by, uint256 id) internal virtual {
        address owner = ownerOf(id);
        _beforeTokenTransfer(owner, address(0), id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            by := shr(96, shl(96, by))
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            // Reload the owner in case it is changed in `_beforeTokenTransfer`.
            owner := shr(96, shl(96, ownershipPacked))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // Load and check the token approval.
            {
                mstore(0x00, owner)
                let approvedAddress := sload(add(1, ownershipSlot))
                // If `by` is not the zero address, do the authorization check.
                // Revert if the `by` is not the owner, nor approved.
                if iszero(or(iszero(by), or(eq(by, owner), eq(by, approvedAddress)))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress {
                    sstore(add(1, ownershipSlot), 0)
                }
            }
            // Clear the owner.
            sstore(ownershipSlot, xor(ownershipPacked, owner))
            // Decrement the balance of `owner`.
            {
                let balanceSlot := keccak256(0x0c, 0x1c)
                sstore(balanceSlot, sub(sload(balanceSlot), 1))
            }
            // Emit the {Transfer} event.
            log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, owner, 0, id)
        }
        _afterTokenTransfer(owner, address(0), id);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL APPROVAL FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `account` is the owner of token `id`, or is approved to managed it.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function _isApprovedOrOwner(address account, uint256 id) internal view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            // Clear the upper 96 bits.
            account := shr(96, shl(96, account))
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, account))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let owner := shr(96, shl(96, sload(ownershipSlot)))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // Check if `account` is the `owner`.
            if iszero(eq(account, owner)) {
                mstore(0x00, owner)
                // Check if `account` is approved to
                if iszero(sload(keccak256(0x0c, 0x30))) {
                    result := eq(account, sload(add(1, ownershipSlot)))
                }
            }
        }
    }

    /// @dev Returns the account approved to manage token `id`.
    /// Returns the zero address instead of reverting if the token does not exist.
    function _getApproved(uint256 id) internal view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := sload(add(1, add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Equivalent to `_approve(address(0), account, id)`.
    function _approve(address account, uint256 id) internal virtual {
        _approve(address(0), account, id);
    }

    /// @dev Sets `account` as the approved account to manage token `id`, using `by`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - If `by` is not the zero address, `by` must be the owner
    ///   or an approved operator for the token owner.
    ///
    /// Emits a {Transfer} event.
    function _approve(address by, address account, uint256 id) internal virtual {
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            account := and(bitmaskAddress, account)
            by := and(bitmaskAddress, by)
            // Load the owner of the token.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let owner := and(bitmaskAddress, sload(ownershipSlot))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // If `by` is not the zero address, do the authorization check.
            // Revert if `by` is not the owner, nor approved.
            if iszero(or(iszero(by), eq(by, owner))) {
                mstore(0x00, owner)
                if iszero(sload(keccak256(0x0c, 0x30))) {
                    mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                    revert(0x1c, 0x04)
                }
            }
            // Sets `account` as the approved account to manage `id`.
            sstore(add(1, ownershipSlot), account)
            // Emit the {Approval} event.
            log4(0x00, 0x00, _APPROVAL_EVENT_SIGNATURE, owner, account, id)
        }
    }

    /// @dev Approve or remove the `operator` as an operator for `by`,
    /// without authorization checks.
    ///
    /// Emits a {ApprovalForAll} event.
    function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            by := shr(96, shl(96, by))
            operator := shr(96, shl(96, operator))
            // Convert to 0 or 1.
            isApproved := iszero(iszero(isApproved))
            // Update the `isApproved` for (`by`, `operator`).
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))
            mstore(0x00, by)
            sstore(keccak256(0x0c, 0x30), isApproved)
            // Emit the {ApprovalForAll} event.
            mstore(0x00, isApproved)
            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, by, operator)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL TRANSFER FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `_transfer(address(0), from, to, id)`.
    function _transfer(address from, address to, uint256 id) internal virtual {
        _transfer(address(0), from, to, id);
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function _transfer(address by, address from, address to, uint256 id) internal virtual {
        _beforeTokenTransfer(from, to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            from := and(bitmaskAddress, from)
            to := and(bitmaskAddress, to)
            by := and(bitmaskAddress, by)
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            let owner := and(bitmaskAddress, ownershipPacked)
            // Revert if `from` is not the owner, or does not exist.
            if iszero(mul(owner, eq(owner, from))) {
                if iszero(owner) {
                    mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`.
                revert(0x1c, 0x04)
            }
            // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
            // Load, check, and update the token approval.
            {
                mstore(0x00, from)
                let approvedAddress := sload(add(1, ownershipSlot))
                // If `by` is not the zero address, do the authorization check.
                // Revert if the `by` is not the owner, nor approved.
                if iszero(or(iszero(by), or(eq(by, from), eq(by, approvedAddress)))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress {
                    sstore(add(1, ownershipSlot), 0)
                }
            }
            // Update with the new owner.
            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))
            // Decrement the balance of `from`.
            {
                let fromBalanceSlot := keccak256(0x0c, 0x1c)
                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))
            }
            // Increment the balance of `to`.
            {
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x1c)
                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
                if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(toBalanceSlot, toBalanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
        _afterTokenTransfer(from, to, id);
    }

    /// @dev Equivalent to `_safeTransfer(from, to, id, "")`.
    function _safeTransfer(address from, address to, uint256 id) internal virtual {
        _safeTransfer(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeTransfer(address from, address to, uint256 id, bytes memory data) internal virtual {
        _transfer(address(0), from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @dev Equivalent to `_safeTransfer(by, from, to, id, "")`.
    function _safeTransfer(address by, address from, address to, uint256 id) internal virtual {
        _safeTransfer(by, from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeTransfer(address by, address from, address to, uint256 id, bytes memory data) internal virtual {
        _transfer(by, from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    HOOKS FOR OVERRIDING                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Hook that is called before any token transfers, including minting and burning.
    function _beforeTokenTransfer(address from, address to, uint256 id) internal virtual {}

    /// @dev Hook that is called after any token transfers, including minting and burning.
    function _afterTokenTransfer(address from, address to, uint256 id) internal virtual {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if `a` has bytecode of non-zero length.
    function _hasCode(address a) private view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := extcodesize(a) // Can handle dirty upper bits.
        }
    }

    /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`.
    /// Reverts if the target does not support the function correctly.
    function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data) private {
        /// @solidity memory-safe-assembly
        assembly {
            // Prepare the calldata.
            let m := mload(0x40)
            let onERC721ReceivedSelector := 0x150b7a02
            mstore(m, onERC721ReceivedSelector)
            mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`.
            mstore(add(m, 0x40), shr(96, shl(96, from)))
            mstore(add(m, 0x60), id)
            mstore(add(m, 0x80), 0x80)
            let n := mload(data)
            mstore(add(m, 0xa0), n)
            if n {
                pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n))
            }
            // Revert if the call reverts.
            if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) {
                if returndatasize() {
                    // Bubble up the revert if the call reverts.
                    returndatacopy(0x00, 0x00, returndatasize())
                    revert(0x00, returndatasize())
                }
                mstore(m, 0)
            }
            // Load the returndata and compare it.
            if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) {
                mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /**
     * @dev Converts a uint256 to its ASCII string decimal representation.
     */
    function _toString(uint256 value) internal pure virtual returns (string memory str) {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
            let m := add(mload(0x40), 0xa0)
            // Update the free memory pointer to allocate.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                str := sub(str, 1)
                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                // prettier-ignore
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
            // Store the length.
            mstore(str, length)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    function _toHexString(address value) internal pure returns (string memory str) {
        str = _toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function _toHexStringNoPrefix(address value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            str := mload(0x40)

            // Allocate the memory.
            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
            // 0x02 bytes for the prefix, and 0x28 bytes for the digits.
            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
            mstore(0x40, add(str, 0x80))

            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            str := add(str, 2)
            mstore(str, 40)

            let o := add(str, 0x20)
            mstore(add(o, 40), 0)

            value := shl(96, value)

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for {
                let i := 0
            } 1 {

            } {
                let p := add(o, add(i, i))
                let temp := byte(i, value)
                mstore8(add(p, 1), mload(and(temp, 15)))
                mstore8(p, mload(shr(4, temp)))
                i := add(i, 1)
                if eq(i, 20) {
                    break
                }
            }
        }
    }
}

/**
 * @dev Interface of ERC721ABurnable.
 */
interface IERC721Burnable {
    /**
     * @dev Burns `tokenId`. See {ERC721A-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) external;
}

/**
 * @title ERC721Burnable.
 *
 * @dev ERC721 token that can be irreversibly burned (destroyed).
 */
abstract contract ERC721Burnable is ERC721, IERC721Burnable {
    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual override {
        _burn(tokenId);
    }
}

/// @notice Based on the reference implementation of the EIP-4494
/// @notice See https://github.com/dievardump/erc721-with-permits and https://eips.ethereum.org/EIPS/eip-4494
/// @author Simon Fremaux (@dievardump) & William SchwabSchwab (@wschwab)
interface IERC4494 {
    function DOMAIN_SEPARATOR() external view returns (bytes32);

    /// @notice Allows to retrieve current nonce for token
    /// @param tokenId token id
    /// @return current token nonce
    function nonces(uint256 tokenId) external view returns (uint256);

    /// @notice function to be called by anyone to approve `spender` using a Permit signature
    /// @dev Anyone can call this to approve `spender`, even a third-party
    /// @param spender the actor to approve
    /// @param tokenId the token id
    /// @param deadline the deadline for the permit to be used
    /// @param signature permit
    function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory signature) external;
}

/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
/// Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  CONSTANTS AND IMMUTABLES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 internal constant _DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    address private immutable _cachedThis;
    uint256 private immutable _cachedChainId;
    bytes32 private immutable _cachedNameHash;
    bytes32 private immutable _cachedVersionHash;
    bytes32 private immutable _cachedDomainSeparator;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CONSTRUCTOR                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Cache the hashes for cheaper runtime gas costs.
    /// In the case of upgradeable contracts (i.e. proxies),
    /// or if the chain id changes due to a hard fork,
    /// the domain separator will be seamlessly calculated on-the-fly.
    constructor() {
        _cachedThis = address(this);
        _cachedChainId = block.chainid;

        (string memory name, string memory version) = _domainNameAndVersion();
        bytes32 nameHash = keccak256(bytes(name));
        bytes32 versionHash = keccak256(bytes(version));
        _cachedNameHash = nameHash;
        _cachedVersionHash = versionHash;

        bytes32 separator;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            separator := keccak256(m, 0xa0)
        }
        _cachedDomainSeparator = separator;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   FUNCTIONS TO OVERRIDE                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Please override this function to return the domain name and version.
    /// ```
    ///     function _domainNameAndVersion()
    ///         internal
    ///         pure
    ///         virtual
    ///         returns (string memory name, string memory version)
    ///     {
    ///         name = "Solady";
    ///         version = "1";
    ///     }
    /// ```
    function _domainNameAndVersion() internal pure virtual returns (string memory name, string memory version);

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _domainSeparator() internal view virtual returns (bytes32 separator) {
        separator = _cachedDomainSeparator;
        if (_cachedDomainSeparatorInvalidated()) {
            separator = _buildDomainSeparator();
        }
    }

    /// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
    /// given `structHash`, as defined in
    /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
    ///
    /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
    /// ```
    ///     bytes32 digest = _hashTypedData(keccak256(abi.encode(
    ///         keccak256("Mail(address to,string contents)"),
    ///         mailTo,
    ///         keccak256(bytes(mailContents))
    ///     )));
    ///     address signer = ECDSA.recover(digest, signature);
    /// ```
    function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
        bytes32 separator = _cachedDomainSeparator;
        if (_cachedDomainSeparatorInvalidated()) {
            separator = _buildDomainSeparator();
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the digest.
            mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
            mstore(0x1a, separator) // Store the domain separator.
            mstore(0x3a, structHash) // Store the struct hash.
            digest := keccak256(0x18, 0x42)
            // Restore the part of the free memory slot that was overwritten.
            mstore(0x3a, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    EIP-5267 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev See: https://eips.ethereum.org/EIPS/eip-5267
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        fields = hex"0f"; // `0b01111`.
        (name, version) = _domainNameAndVersion();
        chainId = block.chainid;
        verifyingContract = address(this);
        salt = salt; // `bytes32(0)`.
        extensions = extensions; // `new uint256[](0)`.
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _buildDomainSeparator() private view returns (bytes32 separator) {
        bytes32 nameHash = _cachedNameHash;
        bytes32 versionHash = _cachedVersionHash;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            separator := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns if the cached domain separator has been invalidated.
    function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
        uint256 cachedChainId = _cachedChainId;
        address cachedThis = _cachedThis;
        /// @solidity memory-safe-assembly
        assembly {
            result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
        }
    }
}

/// @dev OpenZeppelin's ERC721Upgradeable extended with EIP-4494-compliant permits
/// @notice Based on the reference implementation of the EIP-4494
/// @notice See https://github.com/dievardump/erc721-with-permits and https://eips.ethereum.org/EIPS/eip-4494
abstract contract ERC721Permit is IERC4494, EIP712, ERC721 {
    /// @dev value is equal to keccak256("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)")
    bytes32 public constant PERMIT_TYPEHASH = 0x49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad;

    mapping(uint256 => uint256) internal _nonces;

    /// @notice Builds the DOMAIN_SEPARATOR (eip712) at time of use
    /// @dev This is not set as a constant, to ensure that the chainId will change in the event of a chain fork
    /// @return the DOMAIN_SEPARATOR of eip712
    function DOMAIN_SEPARATOR() public view override returns (bytes32) {
        return _domainSeparator();
    }

    /// @notice Allows to retrieve current nonce for token
    /// @param tokenId token id
    /// @return current token nonce
    function nonces(uint256 tokenId) public view override returns (uint256) {
        require(_exists(tokenId), "!EXIST");
        return _nonces[tokenId];
    }

    /// @notice function to be called by anyone to approve `spender` using a Permit signature
    /// @dev Anyone can call this to approve `spender`, even a third-party
    /// @param spender_ the actor to approve
    /// @param tokenId_ the token id
    /// @param deadline_ the deadline for the permit to be used
    /// @param signature_ permit
    function permit(address spender_, uint256 tokenId_, uint256 deadline_, bytes memory signature_) external override {
        require(deadline_ >= block.timestamp, "EXPRIED");

        bytes32 digest = _buildDigest(spender_, tokenId_, _nonces[tokenId_], deadline_);

        (address recoveredAddress, ) = ECDSA.tryRecover(digest, signature_);
        require((recoveredAddress != address(0) && _isApprovedOrOwner(recoveredAddress, tokenId_)), "!PERMIT");

        _approve(spender_, tokenId_);
    }

    /// @notice Builds the permit digest to sign
    /// @param spender_ the token spender
    /// @param tokenId_ the tokenId
    /// @param nonce_ the nonce to make a permit for
    /// @param deadline_ the deadline before when the permit can be used
    /// @return the digest (following eip712) to sign
    function _buildDigest(
        address spender_,
        uint256 tokenId_,
        uint256 nonce_,
        uint256 deadline_
    ) private view returns (bytes32) {
        bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, spender_, tokenId_, nonce_, deadline_));
        return _hashTypedData(structHash);
    }

    /// @dev helper to easily increment a nonce for a given tokenId
    /// @param tokenId the tokenId to increment the nonce for
    function _incrementNonce(uint256 tokenId) internal {
        assembly {
            mstore(0x00, tokenId)
            mstore(0x20, _nonces.slot)
            let key := keccak256(0x00, 0x40)
            sstore(key, add(sload(key), 1))
        }
    }

    function _transfer(address from_, address to_, uint256 tokenId_) internal virtual override {
        // increment the nonce to be sure it can't be reused
        _incrementNonce(tokenId_);

        // do normal transfer
        super._transfer(from_, to_, tokenId_);
    }
}

/**
 * @dev Interface of IERC721URIStorage.
 */
interface IERC721URIStorage {
    event NewBaseTokenURI(string baseTokenURI);

    function baseURI() external view returns (string memory);
}

/**
 * @dev ERC721 token with storage based token URI management.
 */
abstract contract ERC721URIStorage is IERC721URIStorage, ERC721 {
    string internal _baseUri;

    function baseURI() external view override returns (string memory) {
        return _baseURI();
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseUri;
    }

    function _setBaseURI(string memory baseUri_) internal virtual {
        _baseUri = baseUri_;
        emit NewBaseTokenURI(baseUri_);
    }
}

interface IPresale {
    function setMinted(address account_, uint256 quantity_) external;
}

abstract contract ReentrancyGuard {
    error ReentrancyGuard__Locked();
    uint256 private locked = 1;

    modifier nonReentrant() virtual {
        if (locked > 1) revert ReentrancyGuard__Locked();

        locked = 2;

        _;

        locked = 1;
    }
}

library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(address token, address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(address token, address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

contract ETH20AVATAR is ERC721, ERC721Burnable, ERC721Permit, ERC721URIStorage, Ownable, ReentrancyGuard {
    uint256 public constant MAX_SUPLLY = 10000;
    uint256 private _idCounter;
    address public presaleContract;

    /**
     * @dev Initializes the MyBoi NFT.
     * @param name_ The name of the token.
     * @param symbol_ The symbol of the token.
     * @param baseUri_ The base URI for token metadata.
     */
    constructor(
        address presaleContract_,
        string memory name_,
        string memory symbol_,
        string memory baseUri_
    ) ERC721(name_, symbol_) {
        _setBaseURI(baseUri_);
        _idCounter = 1;
        presaleContract = presaleContract_;
    }

    /**
     * @dev Checks if a given token ID exists.
     * @param tokenId_ The ID of the token to check.
     * @return A boolean indicating whether the token exists.
     */
    function exists(uint256 tokenId_) external view returns (bool) {
        return _exists(tokenId_);
    }

    /**
     * @dev Returns the total number of tokens minted.
     * @return The total number of tokens minted.
     */
    function totalMinted() external view returns (uint256) {
        return _idCounter - 1;
    }

    /**
     * @dev Sets the base token URI for token metadata.
     * @param baseTokenURI_ The new base token URI.
     */
    function setBaseTokenURI(string calldata baseTokenURI_) external onlyOwner {
        _setBaseURI(baseTokenURI_);
    }

    function batchMint(uint256 quantity) external nonReentrant {
        address sender = _msgSender();
        IPresale(presaleContract).setMinted(sender, quantity);
        uint256 tokenId = _idCounter;

        for (uint i = 0; i < quantity; ) {
            _safeMint(sender, tokenId);
            unchecked {
                ++tokenId;
                ++i;
            }
        }
        _idCounter = tokenId;
    }

    // The following functions are overrides required by Solidity.

    /**
     * @dev Transfers the ownership of a token from one address to another.
     * @param from_ The current owner of the token.
     * @param to_ The new owner of the token.
     * @param tokenId_ The ID of the token to transfer.
     */
    function _transfer(address from_, address to_, uint256 tokenId_) internal override(ERC721, ERC721Permit) {
        super._transfer(from_, to_, tokenId_);
    }

    /**
     * @dev Returns the base URI for token metadata.
     * @return The base URI for token metadata.
     */
    function _baseURI() internal view virtual override(ERC721, ERC721URIStorage) returns (string memory) {
        return _baseUri;
    }

    /**
     * @dev Returns the name and version of the ERC712.
     * @return The name and version of the contract.
     */
    function _domainNameAndVersion() internal pure override returns (string memory, string memory) {
        return ("ETH20 AVATAR", "1");
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"presaleContract_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"baseUri_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountBalanceOverflow","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"NotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ReentrancyGuard__Locked","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TokenDoesNotExist","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"isApproved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseTokenURI","type":"string"}],"name":"NewBaseTokenURI","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":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPLLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"batchMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"presaleContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseTokenURI_","type":"string"}],"name":"setBaseTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

61012060405260016005553480156200001757600080fd5b5060405162002095380380620020958339810160408190526200003a91620002ce565b306080524660a052828260008062000089604080518082018252600c81526b22aa2419181020ab20aa20a960a11b602080830191909152825180840190935260018352603160f81b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152938401929092529082015246606082015230608082015260a09020610100525060009050620000fb83826200040f565b5060016200010a82826200040f565b50505062000127620001216200016060201b60201c565b62000164565b6200013281620001b6565b5050600160065550600780546001600160a01b0319166001600160a01b039290921691909117905562000510565b3390565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6003620001c482826200040f565b507fe506a59ac6ac58481e880869f6a02855a0a5cba4f4026cc6ee0af056c7e4283f81604051620001f69190620004db565b60405180910390a150565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002345781810151838201526020016200021a565b50506000910152565b600082601f8301126200024f57600080fd5b81516001600160401b03808211156200026c576200026c62000201565b604051601f8301601f19908116603f0116810190828211818310171562000297576200029762000201565b81604052838152866020858801011115620002b157600080fd5b620002c484602083016020890162000217565b9695505050505050565b60008060008060808587031215620002e557600080fd5b84516001600160a01b0381168114620002fd57600080fd5b60208601519094506001600160401b03808211156200031b57600080fd5b62000329888389016200023d565b945060408701519150808211156200034057600080fd5b6200034e888389016200023d565b935060608701519150808211156200036557600080fd5b5062000374878288016200023d565b91505092959194509250565b600181811c908216806200039557607f821691505b602082108103620003b657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200040a57600081815260208120601f850160051c81016020861015620003e55750805b601f850160051c820191505b818110156200040657828155600101620003f1565b5050505b505050565b81516001600160401b038111156200042b576200042b62000201565b62000443816200043c845462000380565b84620003bc565b602080601f8311600181146200047b5760008415620004625750858301515b600019600386901b1c1916600185901b17855562000406565b600085815260208120601f198616915b82811015620004ac578886015182559484019460019091019084016200048b565b5085821015620004cb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020815260008251806020840152620004fc81604085016020870162000217565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161010051611b396200055c60003960008181610e3701526112cb015260006111c00152600061119a015260006111290152600061114c0152611b396000f3fe6080604052600436106101c25760003560e01c806363d9df85116100f75780638da5cb5b11610095578063b88d4fde11610064578063b88d4fde146104f5578063c87b56dd14610508578063e985e9c514610528578063f2fde38b1461055e57600080fd5b80638da5cb5b1461048d57806395d89b41146104ab578063a22cb465146104c0578063a2309ff8146104e057600080fd5b8063715018a6116100d1578063715018a614610410578063745a41bc146104255780638467be0d1461044557806384b0196e1461046557600080fd5b806363d9df85146103bb5780636c0360eb146103db57806370a08231146103f057600080fd5b806330adf81f1161016457806342966c681161013e57806342966c68146103455780634f558e79146103655780635dfb31ce146103855780636352211e1461039b57600080fd5b806330adf81f146102e95780633644e5151461031d57806342842e0e1461033257600080fd5b8063095ea7b3116101a0578063095ea7b314610273578063141a468c1461028857806323b872dd146102b657806330176e13146102c957600080fd5b806301ffc9a7146101c757806306fdde0314610219578063081812fc1461023b575b600080fd5b3480156101d357600080fd5b506102046101e2366004611527565b6301ffc9a760e09190911c9081146380ac58cd821417635b5e139f9091141790565b60405190151581526020015b60405180910390f35b34801561022557600080fd5b5061022e61057e565b60405161021091906115a1565b34801561024757600080fd5b5061025b6102563660046115b4565b610610565b6040516001600160a01b039091168152602001610210565b6102866102813660046115e4565b610653565b005b34801561029457600080fd5b506102a86102a33660046115b4565b610662565b604051908152602001610210565b6102866102c436600461160e565b6106ba565b3480156102d557600080fd5b506102866102e436600461168c565b6107d1565b3480156102f557600080fd5b506102a87f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b34801561032957600080fd5b506102a8610818565b61028661034036600461160e565b610827565b34801561035157600080fd5b506102866103603660046115b4565b610854565b34801561037157600080fd5b506102046103803660046115b4565b610860565b34801561039157600080fd5b506102a861271081565b3480156103a757600080fd5b5061025b6103b63660046115b4565b610871565b3480156103c757600080fd5b5060075461025b906001600160a01b031681565b3480156103e757600080fd5b5061022e6108af565b3480156103fc57600080fd5b506102a861040b3660046116ce565b6108b9565b34801561041c57600080fd5b506102866108f4565b34801561043157600080fd5b506102866104403660046116ff565b610908565b34801561045157600080fd5b506102866104603660046115b4565b6109d5565b34801561047157600080fd5b5061047a610a9c565b60405161021097969594939291906117d4565b34801561049957600080fd5b506004546001600160a01b031661025b565b3480156104b757600080fd5b5061022e610afc565b3480156104cc57600080fd5b506102866104db36600461186a565b610b0b565b3480156104ec57600080fd5b506102a8610b61565b6102866105033660046118a6565b610b72565b34801561051457600080fd5b5061022e6105233660046115b4565b610bcd565b34801561053457600080fd5b50610204610543366004611915565b601c52670a5a2e7a000000006008526000526030600c205490565b34801561056a57600080fd5b506102866105793660046116ce565b610c5b565b60606000805461058d90611948565b80601f01602080910402602001604051908101604052809291908181526020018280546105b990611948565b80156106065780601f106105db57610100808354040283529160200191610606565b820191906000526020600020905b8154815290600101906020018083116105e957829003601f168201915b5050505050905090565b6000818152673ec412a9852d173d60c11b601c52602081208201820180546001600160a01b03166106495763ceea21b66000526004601cfd5b6001015492915050565b61065e338383610cd1565b5050565b600061066d82610d72565b6106a75760405162461bcd60e51b81526020600482015260066024820152650851561254d560d21b60448201526064015b60405180910390fd5b5060009081526002602052604090205490565b6000818152673ec412a9852d173d60c11b3317601c52602090208101810180546001600160a01b039485169493841693811691908286148302610718578261070a5763ceea21b66000526004601cfd5b63a11481006000526004601cfd5b8461072b5763ea553b346000526004601cfd5b856000528160010154925082331486331417610759576030600c205461075957634b6e7f186000526004601cfd5b821561076757600082600101555b85851818905550601c600c8181208054600019019055600084905220805460010163ffffffff81166107a1576301336cea6000526004601cfd5b90558082847fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a45b505050565b6107d9610d94565b61065e82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610dee92505050565b6000610822610e35565b905090565b6108328383836106ba565b813b156107cc576107cc83838360405180602001604052806000815250610e6e565b61085d81610ef8565b50565b600061086b82610d72565b92915050565b6000818152673ec412a9852d173d60c11b601c526020902081018101546001600160a01b0316806108aa5763ceea21b66000526004601cfd5b919050565b6060610822610f03565b6000816108ce57638f4eb6046000526004601cfd5b673ec412a9852d173d60c11b601c528160005263ffffffff601c600c2054169050919050565b6108fc610d94565b6109066000610f12565b565b428210156109425760405162461bcd60e51b81526020600482015260076024820152661156141492515160ca1b604482015260640161069e565b60008381526002602052604081205461095f908690869086610f64565b9050600061096d8284610fe7565b5090506001600160a01b0381161580159061098d575061098d818661102c565b6109c35760405162461bcd60e51b81526020600482015260076024820152660854115493525560ca1b604482015260640161069e565b6109cd8686611098565b505050505050565b600160055411156109f95760405163c0d27a9760e01b815260040160405180910390fd5b6002600555600033600754604051634258912560e01b81526001600160a01b03808416600483015260248201869052929350911690634258912590604401600060405180830381600087803b158015610a5157600080fd5b505af1158015610a65573d6000803e3d6000fd5b50506006549150600090505b83811015610a8f57610a8383836110a4565b60019182019101610a71565b5060065550506001600555565b600f60f81b6060806000808083610aea604080518082018252600c81526b22aa2419181020ab20aa20a960a11b602080830191909152825180840190935260018352603160f81b9083015291565b97989097965046955030945091925090565b60606001805461058d90611948565b801515905081601c52670a5a2e7a0000000060085233600052806030600c2055806000528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160206000a35050565b600060016006546108229190611982565b610b7d8585856106ba565b833b15610bc657610bc685858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610e6e92505050565b5050505050565b6060610bd882610d72565b610bf55760405163677510db60e11b815260040160405180910390fd5b6000610bff610f03565b90506000815111610c1f5760405180602001604052806000815250610c54565b80610c29306110be565b610c32856110e2565b604051602001610c44939291906119a3565b6040516020818303038152906040525b9392505050565b610c63610d94565b6001600160a01b038116610cc85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161069e565b61085d81610f12565b60001960601c828116925083811693508160005283673ec412a9852d173d60c11b17601c5260206000208201820180548216915081610d185763ceea21b66000526004601cfd5b818514851517610d3e57816000526030600c2054610d3e57634b6e7f186000526004601cfd5b6001018390558183827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a450505050565b6000818152673ec412a9852d173d60c11b601c52602090208101015460601b90565b6004546001600160a01b031633146109065760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161069e565b6003610dfa8282611a43565b507fe506a59ac6ac58481e880869f6a02855a0a5cba4f4026cc6ee0af056c7e4283f81604051610e2a91906115a1565b60405180910390a150565b7f0000000000000000000000000000000000000000000000000000000000000000610e5e611126565b15610e6b57610822611171565b90565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015610eb5578060c08401826020870160045afa505b60208360a48301601c860160008a5af1610ede573d15610ed9573d6000803e3d6000fd5b600083525b508060e01b8251146109cd5763d1a57ed66000526004601cfd5b61085d6000826111f9565b60606003805461058d90611948565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604080517f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad60208201526001600160a01b03861691810191909152606081018490526080810183905260a08101829052600090819060c001604051602081830303815290604052805190602001209050610fdd816112c7565b9695505050505050565b600080825160410361101d5760208301516040840151606085015160001a61101187828585611328565b94509450505050611025565b506000905060025b9250929050565b60008181526001600160a01b03928316673ec412a9852d173d60c11b8117601c526020909120820182018054919360019216806110715763ceea21b66000526004601cfd5b80851461109057806000526030600c2054611090578160010154851492505b505092915050565b61065e60008383610cd1565b61065e8282604051806020016040528060008152506113ec565b60606110c98261140a565b8051613078825260020160011990910190815292915050565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806110fc5750819003601f19909101908152919050565b467f000000000000000000000000000000000000000000000000000000000000000014307f000000000000000000000000000000000000000000000000000000000000000014161590565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a0902090565b600061120482610871565b90505060008181526001600160a01b03928316673ec412a9852d173d60c11b8117601c52602090912082018201805491938216918261124b5763ceea21b66000526004601cfd5b8260005281600101548086148487141786151761127a576030600c205461127a57634b6e7f186000526004601cfd5b801561128857600083600101555b5082189055601c600c208054600019019055816000827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4505050565b60007f00000000000000000000000000000000000000000000000000000000000000006112f2611126565b15611302576112ff611171565b90505b67190100000000000060005280601a5282603a52604260182091506000603a5250919050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561135f57506000905060036113e3565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156113b3573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166113dc576000600192509250506113e3565b9150600090505b94509492505050565b6113f68383611479565b823b156107cc576107cc6000848484610e6e565b60606040519050608081016040526f30313233343536373839616263646566600f526002810190506028815260208101600060288201528260601b925060005b808101820184821a600f81165160018301538060041c518253505060018101906012190161144a575050919050565b6001600160a01b0390911690816114985763ea553b346000526004601cfd5b80600052673ec412a9852d173d60c11b601c5260206000208101810180548060601b156114cd5763c991cbb16000526004601cfd5b831790556000829052601c600c20805460010163ffffffff81166114f9576301336cea6000526004601cfd5b9055808260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a45050565b60006020828403121561153957600080fd5b81356001600160e01b031981168114610c5457600080fd5b60005b8381101561156c578181015183820152602001611554565b50506000910152565b6000815180845261158d816020860160208601611551565b601f01601f19169290920160200192915050565b602081526000610c546020830184611575565b6000602082840312156115c657600080fd5b5035919050565b80356001600160a01b03811681146108aa57600080fd5b600080604083850312156115f757600080fd5b611600836115cd565b946020939093013593505050565b60008060006060848603121561162357600080fd5b61162c846115cd565b925061163a602085016115cd565b9150604084013590509250925092565b60008083601f84011261165c57600080fd5b50813567ffffffffffffffff81111561167457600080fd5b60208301915083602082850101111561102557600080fd5b6000806020838503121561169f57600080fd5b823567ffffffffffffffff8111156116b657600080fd5b6116c28582860161164a565b90969095509350505050565b6000602082840312156116e057600080fd5b610c54826115cd565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561171557600080fd5b61171e856115cd565b93506020850135925060408501359150606085013567ffffffffffffffff8082111561174957600080fd5b818701915087601f83011261175d57600080fd5b81358181111561176f5761176f6116e9565b604051601f8201601f19908116603f01168101908382118183101715611797576117976116e9565b816040528281528a60208487010111156117b057600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60ff60f81b881681526000602060e0818401526117f460e084018a611575565b8381036040850152611806818a611575565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156118585783518352928401929184019160010161183c565b50909c9b505050505050505050505050565b6000806040838503121561187d57600080fd5b611886836115cd565b91506020830135801515811461189b57600080fd5b809150509250929050565b6000806000806000608086880312156118be57600080fd5b6118c7866115cd565b94506118d5602087016115cd565b935060408601359250606086013567ffffffffffffffff8111156118f857600080fd5b6119048882890161164a565b969995985093965092949392505050565b6000806040838503121561192857600080fd5b611931836115cd565b915061193f602084016115cd565b90509250929050565b600181811c9082168061195c57607f821691505b60208210810361197c57634e487b7160e01b600052602260045260246000fd5b50919050565b8181038181111561086b57634e487b7160e01b600052601160045260246000fd5b600084516119b5818460208901611551565b8083019050602f60f81b80825285516119d5816001850160208a01611551565b600192019182015283516119f0816002840160208801611551565b0160020195945050505050565b601f8211156107cc57600081815260208120601f850160051c81016020861015611a245750805b601f850160051c820191505b818110156109cd57828155600101611a30565b815167ffffffffffffffff811115611a5d57611a5d6116e9565b611a7181611a6b8454611948565b846119fd565b602080601f831160018114611aa65760008415611a8e5750858301515b600019600386901b1c1916600185901b1785556109cd565b600085815260208120601f198616915b82811015611ad557888601518255948401946001909101908401611ab6565b5085821015611af35787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220a738f2a03f1e06d7014654e59d2b6af7702dc9f199cfeea9592e8d0fa409800764736f6c6343000813003300000000000000000000000081e9ab34d332b51465fdddbd328fbd3134408892000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000c455448323020415641544152000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084554483230415654000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002368747470733a2f2f6170692e6574683230746f6b656e2e636f6d2f6d657461646174610000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106101c25760003560e01c806363d9df85116100f75780638da5cb5b11610095578063b88d4fde11610064578063b88d4fde146104f5578063c87b56dd14610508578063e985e9c514610528578063f2fde38b1461055e57600080fd5b80638da5cb5b1461048d57806395d89b41146104ab578063a22cb465146104c0578063a2309ff8146104e057600080fd5b8063715018a6116100d1578063715018a614610410578063745a41bc146104255780638467be0d1461044557806384b0196e1461046557600080fd5b806363d9df85146103bb5780636c0360eb146103db57806370a08231146103f057600080fd5b806330adf81f1161016457806342966c681161013e57806342966c68146103455780634f558e79146103655780635dfb31ce146103855780636352211e1461039b57600080fd5b806330adf81f146102e95780633644e5151461031d57806342842e0e1461033257600080fd5b8063095ea7b3116101a0578063095ea7b314610273578063141a468c1461028857806323b872dd146102b657806330176e13146102c957600080fd5b806301ffc9a7146101c757806306fdde0314610219578063081812fc1461023b575b600080fd5b3480156101d357600080fd5b506102046101e2366004611527565b6301ffc9a760e09190911c9081146380ac58cd821417635b5e139f9091141790565b60405190151581526020015b60405180910390f35b34801561022557600080fd5b5061022e61057e565b60405161021091906115a1565b34801561024757600080fd5b5061025b6102563660046115b4565b610610565b6040516001600160a01b039091168152602001610210565b6102866102813660046115e4565b610653565b005b34801561029457600080fd5b506102a86102a33660046115b4565b610662565b604051908152602001610210565b6102866102c436600461160e565b6106ba565b3480156102d557600080fd5b506102866102e436600461168c565b6107d1565b3480156102f557600080fd5b506102a87f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b34801561032957600080fd5b506102a8610818565b61028661034036600461160e565b610827565b34801561035157600080fd5b506102866103603660046115b4565b610854565b34801561037157600080fd5b506102046103803660046115b4565b610860565b34801561039157600080fd5b506102a861271081565b3480156103a757600080fd5b5061025b6103b63660046115b4565b610871565b3480156103c757600080fd5b5060075461025b906001600160a01b031681565b3480156103e757600080fd5b5061022e6108af565b3480156103fc57600080fd5b506102a861040b3660046116ce565b6108b9565b34801561041c57600080fd5b506102866108f4565b34801561043157600080fd5b506102866104403660046116ff565b610908565b34801561045157600080fd5b506102866104603660046115b4565b6109d5565b34801561047157600080fd5b5061047a610a9c565b60405161021097969594939291906117d4565b34801561049957600080fd5b506004546001600160a01b031661025b565b3480156104b757600080fd5b5061022e610afc565b3480156104cc57600080fd5b506102866104db36600461186a565b610b0b565b3480156104ec57600080fd5b506102a8610b61565b6102866105033660046118a6565b610b72565b34801561051457600080fd5b5061022e6105233660046115b4565b610bcd565b34801561053457600080fd5b50610204610543366004611915565b601c52670a5a2e7a000000006008526000526030600c205490565b34801561056a57600080fd5b506102866105793660046116ce565b610c5b565b60606000805461058d90611948565b80601f01602080910402602001604051908101604052809291908181526020018280546105b990611948565b80156106065780601f106105db57610100808354040283529160200191610606565b820191906000526020600020905b8154815290600101906020018083116105e957829003601f168201915b5050505050905090565b6000818152673ec412a9852d173d60c11b601c52602081208201820180546001600160a01b03166106495763ceea21b66000526004601cfd5b6001015492915050565b61065e338383610cd1565b5050565b600061066d82610d72565b6106a75760405162461bcd60e51b81526020600482015260066024820152650851561254d560d21b60448201526064015b60405180910390fd5b5060009081526002602052604090205490565b6000818152673ec412a9852d173d60c11b3317601c52602090208101810180546001600160a01b039485169493841693811691908286148302610718578261070a5763ceea21b66000526004601cfd5b63a11481006000526004601cfd5b8461072b5763ea553b346000526004601cfd5b856000528160010154925082331486331417610759576030600c205461075957634b6e7f186000526004601cfd5b821561076757600082600101555b85851818905550601c600c8181208054600019019055600084905220805460010163ffffffff81166107a1576301336cea6000526004601cfd5b90558082847fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a45b505050565b6107d9610d94565b61065e82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610dee92505050565b6000610822610e35565b905090565b6108328383836106ba565b813b156107cc576107cc83838360405180602001604052806000815250610e6e565b61085d81610ef8565b50565b600061086b82610d72565b92915050565b6000818152673ec412a9852d173d60c11b601c526020902081018101546001600160a01b0316806108aa5763ceea21b66000526004601cfd5b919050565b6060610822610f03565b6000816108ce57638f4eb6046000526004601cfd5b673ec412a9852d173d60c11b601c528160005263ffffffff601c600c2054169050919050565b6108fc610d94565b6109066000610f12565b565b428210156109425760405162461bcd60e51b81526020600482015260076024820152661156141492515160ca1b604482015260640161069e565b60008381526002602052604081205461095f908690869086610f64565b9050600061096d8284610fe7565b5090506001600160a01b0381161580159061098d575061098d818661102c565b6109c35760405162461bcd60e51b81526020600482015260076024820152660854115493525560ca1b604482015260640161069e565b6109cd8686611098565b505050505050565b600160055411156109f95760405163c0d27a9760e01b815260040160405180910390fd5b6002600555600033600754604051634258912560e01b81526001600160a01b03808416600483015260248201869052929350911690634258912590604401600060405180830381600087803b158015610a5157600080fd5b505af1158015610a65573d6000803e3d6000fd5b50506006549150600090505b83811015610a8f57610a8383836110a4565b60019182019101610a71565b5060065550506001600555565b600f60f81b6060806000808083610aea604080518082018252600c81526b22aa2419181020ab20aa20a960a11b602080830191909152825180840190935260018352603160f81b9083015291565b97989097965046955030945091925090565b60606001805461058d90611948565b801515905081601c52670a5a2e7a0000000060085233600052806030600c2055806000528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160206000a35050565b600060016006546108229190611982565b610b7d8585856106ba565b833b15610bc657610bc685858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610e6e92505050565b5050505050565b6060610bd882610d72565b610bf55760405163677510db60e11b815260040160405180910390fd5b6000610bff610f03565b90506000815111610c1f5760405180602001604052806000815250610c54565b80610c29306110be565b610c32856110e2565b604051602001610c44939291906119a3565b6040516020818303038152906040525b9392505050565b610c63610d94565b6001600160a01b038116610cc85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161069e565b61085d81610f12565b60001960601c828116925083811693508160005283673ec412a9852d173d60c11b17601c5260206000208201820180548216915081610d185763ceea21b66000526004601cfd5b818514851517610d3e57816000526030600c2054610d3e57634b6e7f186000526004601cfd5b6001018390558183827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a450505050565b6000818152673ec412a9852d173d60c11b601c52602090208101015460601b90565b6004546001600160a01b031633146109065760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161069e565b6003610dfa8282611a43565b507fe506a59ac6ac58481e880869f6a02855a0a5cba4f4026cc6ee0af056c7e4283f81604051610e2a91906115a1565b60405180910390a150565b7f08460449486f80fb8f43820cd0bb31017393173539fa6bc7d0721841d47f8e42610e5e611126565b15610e6b57610822611171565b90565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015610eb5578060c08401826020870160045afa505b60208360a48301601c860160008a5af1610ede573d15610ed9573d6000803e3d6000fd5b600083525b508060e01b8251146109cd5763d1a57ed66000526004601cfd5b61085d6000826111f9565b60606003805461058d90611948565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604080517f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad60208201526001600160a01b03861691810191909152606081018490526080810183905260a08101829052600090819060c001604051602081830303815290604052805190602001209050610fdd816112c7565b9695505050505050565b600080825160410361101d5760208301516040840151606085015160001a61101187828585611328565b94509450505050611025565b506000905060025b9250929050565b60008181526001600160a01b03928316673ec412a9852d173d60c11b8117601c526020909120820182018054919360019216806110715763ceea21b66000526004601cfd5b80851461109057806000526030600c2054611090578160010154851492505b505092915050565b61065e60008383610cd1565b61065e8282604051806020016040528060008152506113ec565b60606110c98261140a565b8051613078825260020160011990910190815292915050565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806110fc5750819003601f19909101908152919050565b467f000000000000000000000000000000000000000000000000000000000000000114307f000000000000000000000000ccac2d3d3e42f63a875185c71e0bde6318ec2d5414161590565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f478afbe3c1b494538cae422e625e9a5660b93570a476df534b896eaf38daadd560208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69181019190915246606082015230608082015260a0902090565b600061120482610871565b90505060008181526001600160a01b03928316673ec412a9852d173d60c11b8117601c52602090912082018201805491938216918261124b5763ceea21b66000526004601cfd5b8260005281600101548086148487141786151761127a576030600c205461127a57634b6e7f186000526004601cfd5b801561128857600083600101555b5082189055601c600c208054600019019055816000827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4505050565b60007f08460449486f80fb8f43820cd0bb31017393173539fa6bc7d0721841d47f8e426112f2611126565b15611302576112ff611171565b90505b67190100000000000060005280601a5282603a52604260182091506000603a5250919050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561135f57506000905060036113e3565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156113b3573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166113dc576000600192509250506113e3565b9150600090505b94509492505050565b6113f68383611479565b823b156107cc576107cc6000848484610e6e565b60606040519050608081016040526f30313233343536373839616263646566600f526002810190506028815260208101600060288201528260601b925060005b808101820184821a600f81165160018301538060041c518253505060018101906012190161144a575050919050565b6001600160a01b0390911690816114985763ea553b346000526004601cfd5b80600052673ec412a9852d173d60c11b601c5260206000208101810180548060601b156114cd5763c991cbb16000526004601cfd5b831790556000829052601c600c20805460010163ffffffff81166114f9576301336cea6000526004601cfd5b9055808260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a45050565b60006020828403121561153957600080fd5b81356001600160e01b031981168114610c5457600080fd5b60005b8381101561156c578181015183820152602001611554565b50506000910152565b6000815180845261158d816020860160208601611551565b601f01601f19169290920160200192915050565b602081526000610c546020830184611575565b6000602082840312156115c657600080fd5b5035919050565b80356001600160a01b03811681146108aa57600080fd5b600080604083850312156115f757600080fd5b611600836115cd565b946020939093013593505050565b60008060006060848603121561162357600080fd5b61162c846115cd565b925061163a602085016115cd565b9150604084013590509250925092565b60008083601f84011261165c57600080fd5b50813567ffffffffffffffff81111561167457600080fd5b60208301915083602082850101111561102557600080fd5b6000806020838503121561169f57600080fd5b823567ffffffffffffffff8111156116b657600080fd5b6116c28582860161164a565b90969095509350505050565b6000602082840312156116e057600080fd5b610c54826115cd565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561171557600080fd5b61171e856115cd565b93506020850135925060408501359150606085013567ffffffffffffffff8082111561174957600080fd5b818701915087601f83011261175d57600080fd5b81358181111561176f5761176f6116e9565b604051601f8201601f19908116603f01168101908382118183101715611797576117976116e9565b816040528281528a60208487010111156117b057600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60ff60f81b881681526000602060e0818401526117f460e084018a611575565b8381036040850152611806818a611575565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156118585783518352928401929184019160010161183c565b50909c9b505050505050505050505050565b6000806040838503121561187d57600080fd5b611886836115cd565b91506020830135801515811461189b57600080fd5b809150509250929050565b6000806000806000608086880312156118be57600080fd5b6118c7866115cd565b94506118d5602087016115cd565b935060408601359250606086013567ffffffffffffffff8111156118f857600080fd5b6119048882890161164a565b969995985093965092949392505050565b6000806040838503121561192857600080fd5b611931836115cd565b915061193f602084016115cd565b90509250929050565b600181811c9082168061195c57607f821691505b60208210810361197c57634e487b7160e01b600052602260045260246000fd5b50919050565b8181038181111561086b57634e487b7160e01b600052601160045260246000fd5b600084516119b5818460208901611551565b8083019050602f60f81b80825285516119d5816001850160208a01611551565b600192019182015283516119f0816002840160208801611551565b0160020195945050505050565b601f8211156107cc57600081815260208120601f850160051c81016020861015611a245750805b601f850160051c820191505b818110156109cd57828155600101611a30565b815167ffffffffffffffff811115611a5d57611a5d6116e9565b611a7181611a6b8454611948565b846119fd565b602080601f831160018114611aa65760008415611a8e5750858301515b600019600386901b1c1916600185901b1785556109cd565b600085815260208120601f198616915b82811015611ad557888601518255948401946001909101908401611ab6565b5085821015611af35787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220a738f2a03f1e06d7014654e59d2b6af7702dc9f199cfeea9592e8d0fa409800764736f6c63430008130033

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

00000000000000000000000081e9ab34d332b51465fdddbd328fbd3134408892000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000c455448323020415641544152000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084554483230415654000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002368747470733a2f2f6170692e6574683230746f6b656e2e636f6d2f6d657461646174610000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : presaleContract_ (address): 0x81e9Ab34D332b51465fDDdbd328fbd3134408892
Arg [1] : name_ (string): ETH20 AVATAR
Arg [2] : symbol_ (string): ETH20AVT
Arg [3] : baseUri_ (string): https://api.eth20token.com/metadata

-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 00000000000000000000000081e9ab34d332b51465fdddbd328fbd3134408892
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [5] : 4554483230204156415441520000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [7] : 4554483230415654000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000023
Arg [9] : 68747470733a2f2f6170692e6574683230746f6b656e2e636f6d2f6d65746164
Arg [10] : 6174610000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

92610:2977:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44516:387;;;;;;;;;;-1:-1:-1;44516:387:0;;;;;:::i;:::-;44834:10;44697:3;44693:21;;;;44828:17;;;44853:10;44847:17;;44825:40;44873:10;44867:17;;;44822:63;;44516:387;;;;470:14:1;;463:22;445:41;;433:2;418:18;44516:387:0;;;;;;;;34903:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;37546:553::-;;;;;;;;;;-1:-1:-1;37546:553:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1602:32:1;;;1584:51;;1572:2;1557:18;37546:553:0;1438:203:1;38402:121:0;;;;;;:::i;:::-;;:::i;:::-;;83345:160;;;;;;;;;;-1:-1:-1;83345:160:0;;;;;:::i;:::-;;:::i;:::-;;;2229:25:1;;;2217:2;2202:18;83345:160:0;2083:177:1;40189:3097:0;;;;;;:::i;:::-;;:::i;93993:120::-;;;;;;;;;;-1:-1:-1;93993:120:0;;;;;:::i;:::-;;:::i;82696:108::-;;;;;;;;;;-1:-1:-1;82696:108:0;82738:66;82696:108;;83096:111;;;;;;;;;;;;;:::i;43360:201::-;;;;;;:::i;:::-;;:::i;73158:88::-;;;;;;;;;;-1:-1:-1;73158:88:0;;;;;:::i;:::-;;:::i;93523:106::-;;;;;;;;;;-1:-1:-1;93523:106:0;;;;;:::i;:::-;;:::i;92722:42::-;;;;;;;;;;;;92759:5;92722:42;;36370:341;;;;;;;;;;-1:-1:-1;36370:341:0;;;;;:::i;:::-;;:::i;92804:30::-;;;;;;;;;;-1:-1:-1;92804:30:0;;;;-1:-1:-1;;;;;92804:30:0;;;86090:102;;;;;;;;;;;;;:::i;36861:545::-;;;;;;;;;;-1:-1:-1;36861:545:0;;;;;:::i;:::-;;:::i;2588:103::-;;;;;;;;;;;;;:::i;83867:507::-;;;;;;;;;;-1:-1:-1;83867:507:0;;;;;:::i;:::-;;:::i;94121:429::-;;;;;;;;;;-1:-1:-1;94121:429:0;;;;;:::i;:::-;;:::i;80265:616::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;1947:87::-;;;;;;;;;;-1:-1:-1;2020:6:0;;-1:-1:-1;;;;;2020:6:0;1947:87;;35053:95;;;;;;;;;;;;;:::i;39125:697::-;;;;;;;;;;-1:-1:-1;39125:697:0;;;;;:::i;:::-;;:::i;93762:95::-;;;;;;;;;;;;;:::i;44078:224::-;;;;;;:::i;:::-;;:::i;35232:384::-;;;;;;;;;;-1:-1:-1;35232:384:0;;;;;:::i;:::-;;:::i;38617:364::-;;;;;;;;;;-1:-1:-1;38617:364:0;;;;;:::i;:::-;38804:4;38797:22;38846:31;38840:4;38833:45;38705:11;38892:19;38957:4;38951;38941:21;38935:28;;38617:364;2846:201;;;;;;;;;;-1:-1:-1;2846:201:0;;;;;:::i;:::-;;:::i;34903:91::-;34948:13;34981:5;34974:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34903:91;:::o;37546:553::-;37608:14;37703:16;;;-1:-1:-1;;;37740:4:0;37733:38;37838:4;37822:21;;37814:30;;37806:39;;37885:20;;-1:-1:-1;;;;;37869:38:0;37859:170;;37941:10;37935:4;37928:24;38009:4;38003;37996:18;37859:170;38063:1;38059:21;38053:28;;37546:553;-1:-1:-1;;37546:553:0:o;38402:121::-;38482:33;38491:10;38503:7;38512:2;38482:8;:33::i;:::-;38402:121;;:::o;83345:160::-;83408:7;83436:16;83444:7;83436;:16::i;:::-;83428:35;;;;-1:-1:-1;;;83428:35:0;;8109:2:1;83428:35:0;;;8091:21:1;8148:1;8128:18;;;8121:29;-1:-1:-1;;;8166:18:1;;;8159:36;8212:18;;83428:35:0;;;;;;;;;-1:-1:-1;83481:16:0;;;;:7;:16;;;;;;;83345:160::o;40189:3097::-;40471:1;40619:16;;;-1:-1:-1;;;40691:8:0;40662:38;40656:4;40649:52;40768:4;40752:21;;40744:30;;40736:39;;40812:20;;-1:-1:-1;;;;;40496:25:0;;;;40541:23;;;;40859:36;;;40736:39;41000:15;;;40989:27;;40979:335;;41047:5;41037:149;;41090:10;41084:4;41077:24;41162:4;41156;41149:18;41037:149;41217:10;41211:4;41204:24;41294:4;41288;41281:18;40979:335;41390:2;41380:138;;41426:10;41420:4;41413:24;41498:4;41492;41485:18;41380:138;41624:4;41618;41611:18;41683:13;41680:1;41676:21;41670:28;41647:51;;41835:15;41825:8;41822:29;41815:4;41805:8;41802:18;41799:53;41789:293;;41909:4;41903;41893:21;41887:28;41877:186;;41957:10;41951:4;41944:24;42035:4;42029;42022:18;41877:186;42159:15;42156:93;;;42228:1;42212:13;42209:1;42205:21;42198:32;42156:93;42364:13;;;42343:35;42321:58;;-1:-1:-1;42500:4:0;42494;42484:21;;;42551:22;;-1:-1:-1;;42547:30:0;42523:55;;-1:-1:-1;42673:16:0;;;42728:21;42798:20;;42575:1;42794:28;42875:20;42850:46;;42840:195;;42934:10;42928:4;42921:24;43011:4;43005;42998:18;42840:195;43053:42;;43221:2;43217;43211:4;43184:25;43178:4;;43167:57;43245:33;40189:3097;;;:::o;93993:120::-;1833:13;:11;:13::i;:::-;94079:26:::1;94091:13;;94079:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;94079:11:0::1;::::0;-1:-1:-1;;;94079:26:0:i:1;83096:111::-:0;83154:7;83181:18;:16;:18::i;:::-;83174:25;;83096:111;:::o;43360:201::-;43458:26;43471:4;43477:2;43481;43458:12;:26::i;:::-;66808:14;;43495:58;;;43513:40;43536:4;43542:2;43546;43513:40;;;;;;;;;;;;:22;:40::i;73158:88::-;73224:14;73230:7;73224:5;:14::i;:::-;73158:88;:::o;93523:106::-;93580:4;93604:17;93612:8;93604:7;:17::i;:::-;93597:24;93523:106;-1:-1:-1;;93523:106:0:o;36370:341::-;36428:14;45854:16;;;-1:-1:-1;;;45891:4:0;45884:38;46000:4;45984:21;;45976:30;;45968:39;;45962:46;-1:-1:-1;;;;;45946:64:0;;36555:138;;36605:10;36599:4;36592:24;36673:4;36667;36660:18;36555:138;36370:341;;;:::o;86090:102::-;86141:13;86174:10;:8;:10::i;36861:545::-;36924:14;37088:5;37078:146;;37127:10;37121:4;37114:24;37204:4;37198;37191:18;37078:146;-1:-1:-1;;;37245:4:0;37238:38;37303:5;37297:4;37290:19;37367:20;37359:4;37353;37343:21;37337:28;37333:55;37323:65;;36861:545;;;:::o;2588:103::-;1833:13;:11;:13::i;:::-;2653:30:::1;2680:1;2653:18;:30::i;:::-;2588:103::o:0;83867:507::-;84013:15;84000:9;:28;;83992:48;;;;-1:-1:-1;;;83992:48:0;;8443:2:1;83992:48:0;;;8425:21:1;8482:1;8462:18;;;8455:29;-1:-1:-1;;;8500:18:1;;;8493:37;8547:18;;83992:48:0;8241:330:1;83992:48:0;84053:14;84103:17;;;:7;:17;;;;;;84070:62;;84083:8;;84093;;84122:9;84070:12;:62::i;:::-;84053:79;;84146:24;84176:36;84193:6;84201:10;84176:16;:36::i;:::-;-1:-1:-1;84145:67:0;-1:-1:-1;;;;;;84232:30:0;;;;;;:80;;;84266:46;84285:16;84303:8;84266:18;:46::i;:::-;84223:102;;;;-1:-1:-1;;;84223:102:0;;8778:2:1;84223:102:0;;;8760:21:1;8817:1;8797:18;;;8790:29;-1:-1:-1;;;8835:18:1;;;8828:37;8882:18;;84223:102:0;8576:330:1;84223:102:0;84338:28;84347:8;84357;84338;:28::i;:::-;83981:393;;83867:507;;;;:::o;94121:429::-;86733:1;86724:6;;:10;86720:48;;;86743:25;;-1:-1:-1;;;86743:25:0;;;;;;;;;;;86720:48;86790:1;86781:6;:10;94191:14:::1;736:10:::0;94240:15:::1;::::0;94231:53:::1;::::0;-1:-1:-1;;;94231:53:0;;-1:-1:-1;;;;;9103:32:1;;;94231:53:0::1;::::0;::::1;9085:51:1::0;9152:18;;;9145:34;;;94191:29:0;;-1:-1:-1;94240:15:0;::::1;::::0;94231:35:::1;::::0;9058:18:1;;94231:53:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;94313:10:0::1;::::0;;-1:-1:-1;94295:15:0::1;::::0;-1:-1:-1;94336:176:0::1;94357:8;94353:1;:12;94336:176;;;94384:26;94394:6;94402:7;94384:9;:26::i;:::-;94454:9;::::0;;::::1;::::0;94482:3:::1;94336:176;;;-1:-1:-1::0;94522:10:0::1;:20:::0;-1:-1:-1;;86827:1:0;86818:6;:10;94121:429::o;80265:616::-;-1:-1:-1;;;80396:18:0;;80368:13;;;80396:18;80676:23;95548:28;;;;;;;;;;;-1:-1:-1;;;95548:28:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;95548:28:0;;;;;95442:142;80676:23;80265:616;;80658:41;;;-1:-1:-1;80720:13:0;;-1:-1:-1;80772:4:0;;-1:-1:-1;80265:616:0;;-1:-1:-1;80265:616:0;:::o;35053:95::-;35100:13;35133:7;35126:14;;;;;:::i;39125:697::-;39344:10;39337:18;39330:26;39316:40;;39455:8;39449:4;39442:22;39491:31;39485:4;39478:45;39550:8;39544:4;39537:22;39603:10;39596:4;39590;39580:21;39573:41;39690:10;39684:4;39677:24;39793:8;39789:2;39785:17;39781:2;39777:26;39767:8;39732:33;39726:4;39720;39715:89;39125:697;;:::o;93762:95::-;93808:7;93848:1;93835:10;;:14;;;;:::i;44078:224::-;44197:26;44210:4;44216:2;44220;44197:12;:26::i;:::-;66808:14;;44234:60;;;44252:42;44275:4;44281:2;44285;44289:4;;44252:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44252:22:0;;-1:-1:-1;;;44252:42:0:i;:::-;44078:224;;;;;:::o;35232:384::-;35296:13;35327:16;35335:7;35327;:16::i;:::-;35322:49;;35352:19;;-1:-1:-1;;;35352:19:0;;;;;;;;;;;35322:49;35384:21;35408:10;:8;:10::i;:::-;35384:34;;35473:1;35455:7;35449:21;:25;:159;;;;;;;;;;;;;;;;;35518:7;35532:27;35553:4;35532:12;:27::i;:::-;35566:18;35576:7;35566:9;:18::i;:::-;35501:84;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;35449:159;35429:179;35232:384;-1:-1:-1;;;35232:384:0:o;2846:201::-;1833:13;:11;:13::i;:::-;-1:-1:-1;;;;;2935:22:0;::::1;2927:73;;;::::0;-1:-1:-1;;;2927:73:0;;10626:2:1;2927:73:0::1;::::0;::::1;10608:21:1::0;10665:2;10645:18;;;10638:30;10704:34;10684:18;;;10677:62;-1:-1:-1;;;10755:18:1;;;10748:36;10801:19;;2927:73:0::1;10424:402:1::0;2927:73:0::1;3011:28;3030:8;3011:18;:28::i;57175:1466::-:0;57361:1;57357:6;57353:2;57349:15;57409:7;57393:14;57389:28;57378:39;;57457:2;57441:14;57437:23;57431:29;;57532:2;57526:4;57519:16;57591:2;-1:-1:-1;;;57562:32:0;57556:4;57549:46;57662:4;57656;57646:21;57642:2;57638:30;57634:2;57630:39;57722:13;57716:20;57700:14;57696:41;57683:54;;57813:5;57803:137;;57852:10;57846:4;57839:24;57920:4;57914;57907:18;57803:137;58126:5;58122:2;58119:13;58114:2;58107:10;58104:29;58094:286;;58167:5;58161:4;58154:19;58223:4;58217;58207:21;58201:28;58191:174;;58267:10;58261:4;58254:24;58341:4;58335;58328:18;58191:174;58476:1;58472:21;58465:38;;;58620:2;58495:7;58604:5;58577:25;58571:4;;58560:63;;57175:1466;;;:::o;45242:317::-;45302:11;45394:16;;;-1:-1:-1;;;45431:4:0;45424:38;45532:4;45516:21;;45508:30;;45500:39;45494:46;45490:2;45486:55;;45242:317::o;2112:132::-;2020:6;;-1:-1:-1;;;;;2020:6:0;736:10;2176:23;2168:68;;;;-1:-1:-1;;;2168:68:0;;11033:2:1;2168:68:0;;;11015:21:1;;;11052:18;;;11045:30;11111:34;11091:18;;;11084:62;11163:18;;2168:68:0;10831:356:1;86317:141:0;86390:8;:19;86401:8;86390;:19;:::i;:::-;;86425:25;86441:8;86425:25;;;;;;:::i;:::-;;;;;;;;86317:141;:::o;78313:244::-;78414:22;78451:35;:33;:35::i;:::-;78447:103;;;78515:23;:21;:23::i;78447:103::-;78313:244;:::o;67035:1452::-;67264:4;67258:11;67315:10;67349:24;67346:1;67339:35;67409:8;67402:4;67399:1;67395:12;67388:30;67518:4;67514:2;67510:13;67506:2;67502:22;67495:4;67492:1;67488:12;67481:44;67560:2;67553:4;67550:1;67546:12;67539:24;67598:4;67591;67588:1;67584:12;67577:26;67632:4;67626:11;67672:1;67665:4;67662:1;67658:12;67651:23;67691:1;67688:101;;;67771:1;67764:4;67761:1;67757:12;67754:1;67747:4;67741;67737:15;67734:1;67727:5;67716:57;67712:62;67688:101;67907:4;67904:1;67897:4;67894:1;67890:12;67883:4;67880:1;67876:12;67873:1;67869:2;67862:5;67857:55;67847:355;;67936:16;67933:224;;;68069:16;68063:4;68057;68042:44;68121:16;68115:4;68108:30;67933:224;68185:1;68182;68175:12;67847:355;;68300:24;68295:3;68291:34;68287:1;68281:8;68278:48;68268:201;;68360:10;68354:4;68347:24;68449:4;68443;68436:18;51999:84;52054:21;52068:1;52072:2;52054:5;:21::i;95170:135::-;95256:13;95289:8;95282:15;;;;;:::i;3207:191::-;3300:6;;;-1:-1:-1;;;;;3317:17:0;;;-1:-1:-1;;;;;;3317:17:0;;;;;;;3350:40;;3300:6;;;3317:17;3300:6;;3350:40;;3281:16;;3350:40;3270:128;3207:191;:::o;84695:328::-;84904:66;;;82738;84904;;;13655:25:1;-1:-1:-1;;;;;13716:32:1;;13696:18;;;13689:60;;;;13765:18;;;13758:34;;;13808:18;;;13801:34;;;13851:19;;;13844:35;;;84853:7:0;;;;13627:19:1;;84904:66:0;;;;;;;;;;;;84894:77;;;;;;84873:98;;84989:26;85004:10;84989:14;:26::i;:::-;84982:33;84695:328;-1:-1:-1;;;;;;84695:328:0:o;22270:747::-;22351:7;22360:12;22389:9;:16;22409:2;22389:22;22385:625;;22733:4;22718:20;;22712:27;22783:4;22768:20;;22762:27;22841:4;22826:20;;22820:27;22428:9;22812:36;22884:25;22895:4;22812:36;22712:27;22762;22884:10;:25::i;:::-;22877:32;;;;;;;;;22385:625;-1:-1:-1;22958:1:0;;-1:-1:-1;22962:35:0;22385:625;22270:747;;;;;:::o;55046:1131::-;55134:11;55383:16;;;-1:-1:-1;;;;;55303:25:0;;;-1:-1:-1;;;55426:37:0;;55420:4;55413:51;55531:4;55515:21;;;55507:30;;55499:39;;55581:20;;55303:25;;55236:1;;55565:38;;55669:137;;55718:10;55712:4;55705:24;55786:4;55780;55773:18;55669:137;55893:5;55884:7;55881:18;55871:288;;55933:5;55927:4;55920:19;56043:4;56037;56027:21;56021:28;56011:133;;56109:13;56106:1;56102:21;56096:28;56087:7;56084:41;56074:51;;56011:133;55871:288;;55046:1131;;;;:::o;56731:116::-;56806:33;56823:1;56827:7;56836:2;56806:8;:33::i;50998:100::-;51069:21;51079:2;51083;51069:21;;;;;;;;;;;;:9;:21::i;70498:447::-;70558:17;70594:27;70615:5;70594:20;:27::i;:::-;70721:10;;70784:6;70772:19;;70733:1;70717:18;-1:-1:-1;;70838:11:0;;;70884:22;;;70838:11;70498:447;-1:-1:-1;;70498:447:0:o;68589:1745::-;68654:17;69088:4;69081;69075:11;69071:22;69180:1;69174:4;69167:15;69255:4;69252:1;69248:12;69241:19;;;69337:1;69332:3;69325:14;69441:3;69680:5;69662:428;69728:1;69723:3;69719:11;69712:18;;69899:2;69893:4;69889:13;69885:2;69881:22;69876:3;69868:36;69993:2;69983:13;;70050:25;69662:428;70050:25;-1:-1:-1;70120:13:0;;;-1:-1:-1;;70235:14:0;;;70297:19;;;70235:14;68589:1745;-1:-1:-1;68589:1745:0:o;81898:347::-;82173:9;82013:14;82170:28;82203:9;82059:11;82200:25;82166:60;82159:68;;81898:347::o;81228:587::-;81492:4;81486:11;;81554:16;81544:27;;81332:15;81599:4;81592:12;;81585:30;81380:18;81636:12;;;81629:33;;;;81697:9;81690:4;81683:12;;81676:31;81742:9;81735:4;81728:12;;81721:31;81792:4;81779:18;;;81228:587::o;52383:2204::-;52450:13;52466:11;52474:2;52466:7;:11::i;:::-;52450:27;;-1:-1:-1;52739:4:0;52732:16;;;-1:-1:-1;;;;;52657:20:0;;;-1:-1:-1;;;52775:32:0;;52769:4;52762:46;52875:4;52859:21;;;52851:30;;52843:39;;52919:20;;52657;;53044:33;;;;53143:137;;53192:10;53186:4;53179:24;53260:4;53254;53247:18;53143:137;53377:5;53371:4;53364:19;53437:13;53434:1;53430:21;53424:28;53672:15;53668:2;53665:23;53657:5;53653:2;53650:13;53647:42;53642:2;53635:10;53632:58;53622:298;;53747:4;53741;53731:21;53725:28;53715:186;;53795:10;53789:4;53782:24;53873:4;53867;53860:18;53715:186;53997:15;53994:93;;;54066:1;54050:13;54047:1;54043:21;54036:32;53994:93;-1:-1:-1;54171:27:0;;54149:50;;54317:4;54311;54301:21;54364:18;;-1:-1:-1;;54360:26:0;54340:47;;54513:2;-1:-1:-1;54192:5:0;54476:25;-1:-1:-1;;54459:57:0;40189:3097;;;:::o;79183:728::-;79258:14;79305:22;79342:35;:33;:35::i;:::-;79338:103;;;79406:23;:21;:23::i;:::-;79394:35;;79338:103;79568:18;79562:4;79555:32;79635:9;79629:4;79622:23;79703:10;79697:4;79690:24;79780:4;79774;79764:21;79754:31;;79891:1;79885:4;79878:15;79504:400;79183:728;;;:::o;25203:1477::-;25291:7;;26225:66;26212:79;;26208:163;;;-1:-1:-1;26324:1:0;;-1:-1:-1;26328:30:0;26308:51;;26208:163;26485:24;;;26468:14;26485:24;;;;;;;;;14117:25:1;;;14190:4;14178:17;;14158:18;;;14151:45;;;;14212:18;;;14205:34;;;14255:18;;;14248:34;;;26485:24:0;;14089:19:1;;26485:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;26485:24:0;;-1:-1:-1;;26485:24:0;;;-1:-1:-1;;;;;;;26524:20:0;;26520:103;;26577:1;26581:29;26561:50;;;;;;;26520:103;26643:6;-1:-1:-1;26651:20:0;;-1:-1:-1;25203:1477:0;;;;;;;;:::o;51463:188::-;51553:13;51559:2;51563;51553:5;:13::i;:::-;66808:14;;51577:66;;;51595:48;51626:1;51630:2;51634;51638:4;51595:22;:48::i;71086:1412::-;71154:17;71265:4;71259:11;71252:18;;71598:4;71593:3;71589:14;71583:4;71576:28;71692:34;71686:4;71679:48;71759:1;71754:3;71750:11;71743:18;;71787:2;71782:3;71775:15;71824:4;71819:3;71815:14;71862:1;71857:2;71854:1;71850:10;71843:21;71897:5;71893:2;71889:14;71880:23;;72121:1;72089:391;72201:1;72198;72194:9;72191:1;72187:17;72242:5;72239:1;72234:14;72301:2;72295:4;72291:13;72285:20;72281:1;72278;72274:9;72266:40;72348:4;72345:1;72341:12;72335:19;72332:1;72324:31;-1:-1:-1;;72385:1:0;72378:9;;;-1:-1:-1;;72408:9:0;72089:391;72405:60;72093:44;;71086:1412;;;:::o;49223:1714::-;-1:-1:-1;;;;;49456:20:0;;;;;49542:138;;49588:10;49582:4;49575:24;49660:4;49654;49647:18;49542:138;49748:2;49742:4;49735:16;-1:-1:-1;;;49772:4:0;49765:38;49870:4;49864;49854:21;49850:2;49846:30;49842:2;49838:39;49920:13;49914:20;50011:15;50007:2;50003:24;50000:149;;;50060:10;50054:4;50047:24;50129:4;50123;50116:18;50000:149;50224:23;;50202:46;;50340:4;50333:16;;;50402:4;50396;50386:21;50454:18;;50474:1;50450:26;50527:20;50504:44;;50494:193;;50586:10;50580:4;50573:24;50663:4;50657;50650:18;50494:193;50705:38;;50866:2;50862;50859:1;50832:25;50859:1;;50815:54;38402:121;;:::o;14:286:1:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:1;;209:43;;199:71;;266:1;263;256:12;497:250;582:1;592:113;606:6;603:1;600:13;592:113;;;682:11;;;676:18;663:11;;;656:39;628:2;621:10;592:113;;;-1:-1:-1;;739:1:1;721:16;;714:27;497:250::o;752:271::-;794:3;832:5;826:12;859:6;854:3;847:19;875:76;944:6;937:4;932:3;928:14;921:4;914:5;910:16;875:76;:::i;:::-;1005:2;984:15;-1:-1:-1;;980:29:1;971:39;;;;1012:4;967:50;;752:271;-1:-1:-1;;752:271:1:o;1028:220::-;1177:2;1166:9;1159:21;1140:4;1197:45;1238:2;1227:9;1223:18;1215:6;1197:45;:::i;1253:180::-;1312:6;1365:2;1353:9;1344:7;1340:23;1336:32;1333:52;;;1381:1;1378;1371:12;1333:52;-1:-1:-1;1404:23:1;;1253:180;-1:-1:-1;1253:180:1:o;1646:173::-;1714:20;;-1:-1:-1;;;;;1763:31:1;;1753:42;;1743:70;;1809:1;1806;1799:12;1824:254;1892:6;1900;1953:2;1941:9;1932:7;1928:23;1924:32;1921:52;;;1969:1;1966;1959:12;1921:52;1992:29;2011:9;1992:29;:::i;:::-;1982:39;2068:2;2053:18;;;;2040:32;;-1:-1:-1;;;1824:254:1:o;2265:328::-;2342:6;2350;2358;2411:2;2399:9;2390:7;2386:23;2382:32;2379:52;;;2427:1;2424;2417:12;2379:52;2450:29;2469:9;2450:29;:::i;:::-;2440:39;;2498:38;2532:2;2521:9;2517:18;2498:38;:::i;:::-;2488:48;;2583:2;2572:9;2568:18;2555:32;2545:42;;2265:328;;;;;:::o;2598:348::-;2650:8;2660:6;2714:3;2707:4;2699:6;2695:17;2691:27;2681:55;;2732:1;2729;2722:12;2681:55;-1:-1:-1;2755:20:1;;2798:18;2787:30;;2784:50;;;2830:1;2827;2820:12;2784:50;2867:4;2859:6;2855:17;2843:29;;2919:3;2912:4;2903:6;2895;2891:19;2887:30;2884:39;2881:59;;;2936:1;2933;2926:12;2951:411;3022:6;3030;3083:2;3071:9;3062:7;3058:23;3054:32;3051:52;;;3099:1;3096;3089:12;3051:52;3139:9;3126:23;3172:18;3164:6;3161:30;3158:50;;;3204:1;3201;3194:12;3158:50;3243:59;3294:7;3285:6;3274:9;3270:22;3243:59;:::i;:::-;3321:8;;3217:85;;-1:-1:-1;2951:411:1;-1:-1:-1;;;;2951:411:1:o;3549:186::-;3608:6;3661:2;3649:9;3640:7;3636:23;3632:32;3629:52;;;3677:1;3674;3667:12;3629:52;3700:29;3719:9;3700:29;:::i;3740:127::-;3801:10;3796:3;3792:20;3789:1;3782:31;3832:4;3829:1;3822:15;3856:4;3853:1;3846:15;3872:1132;3967:6;3975;3983;3991;4044:3;4032:9;4023:7;4019:23;4015:33;4012:53;;;4061:1;4058;4051:12;4012:53;4084:29;4103:9;4084:29;:::i;:::-;4074:39;;4160:2;4149:9;4145:18;4132:32;4122:42;;4211:2;4200:9;4196:18;4183:32;4173:42;;4266:2;4255:9;4251:18;4238:32;4289:18;4330:2;4322:6;4319:14;4316:34;;;4346:1;4343;4336:12;4316:34;4384:6;4373:9;4369:22;4359:32;;4429:7;4422:4;4418:2;4414:13;4410:27;4400:55;;4451:1;4448;4441:12;4400:55;4487:2;4474:16;4509:2;4505;4502:10;4499:36;;;4515:18;;:::i;:::-;4590:2;4584:9;4558:2;4644:13;;-1:-1:-1;;4640:22:1;;;4664:2;4636:31;4632:40;4620:53;;;4688:18;;;4708:22;;;4685:46;4682:72;;;4734:18;;:::i;:::-;4774:10;4770:2;4763:22;4809:2;4801:6;4794:18;4849:7;4844:2;4839;4835;4831:11;4827:20;4824:33;4821:53;;;4870:1;4867;4860:12;4821:53;4926:2;4921;4917;4913:11;4908:2;4900:6;4896:15;4883:46;4971:1;4966:2;4961;4953:6;4949:15;4945:24;4938:35;4992:6;4982:16;;;;;;;3872:1132;;;;;;;:::o;5009:1259::-;5415:3;5410;5406:13;5398:6;5394:26;5383:9;5376:45;5357:4;5440:2;5478:3;5473:2;5462:9;5458:18;5451:31;5505:46;5546:3;5535:9;5531:19;5523:6;5505:46;:::i;:::-;5599:9;5591:6;5587:22;5582:2;5571:9;5567:18;5560:50;5633:33;5659:6;5651;5633:33;:::i;:::-;5697:2;5682:18;;5675:34;;;-1:-1:-1;;;;;5746:32:1;;5740:3;5725:19;;5718:61;5766:3;5795:19;;5788:35;;;5860:22;;;5854:3;5839:19;;5832:51;5932:13;;5954:22;;;6030:15;;;;-1:-1:-1;5992:15:1;;;;-1:-1:-1;6073:169:1;6087:6;6084:1;6081:13;6073:169;;;6148:13;;6136:26;;6217:15;;;;6182:12;;;;6109:1;6102:9;6073:169;;;-1:-1:-1;6259:3:1;;5009:1259;-1:-1:-1;;;;;;;;;;;;5009:1259:1:o;6273:347::-;6338:6;6346;6399:2;6387:9;6378:7;6374:23;6370:32;6367:52;;;6415:1;6412;6405:12;6367:52;6438:29;6457:9;6438:29;:::i;:::-;6428:39;;6517:2;6506:9;6502:18;6489:32;6564:5;6557:13;6550:21;6543:5;6540:32;6530:60;;6586:1;6583;6576:12;6530:60;6609:5;6599:15;;;6273:347;;;;;:::o;6625:627::-;6722:6;6730;6738;6746;6754;6807:3;6795:9;6786:7;6782:23;6778:33;6775:53;;;6824:1;6821;6814:12;6775:53;6847:29;6866:9;6847:29;:::i;:::-;6837:39;;6895:38;6929:2;6918:9;6914:18;6895:38;:::i;:::-;6885:48;;6980:2;6969:9;6965:18;6952:32;6942:42;;7035:2;7024:9;7020:18;7007:32;7062:18;7054:6;7051:30;7048:50;;;7094:1;7091;7084:12;7048:50;7133:59;7184:7;7175:6;7164:9;7160:22;7133:59;:::i;:::-;6625:627;;;;-1:-1:-1;6625:627:1;;-1:-1:-1;7211:8:1;;7107:85;6625:627;-1:-1:-1;;;6625:627:1:o;7257:260::-;7325:6;7333;7386:2;7374:9;7365:7;7361:23;7357:32;7354:52;;;7402:1;7399;7392:12;7354:52;7425:29;7444:9;7425:29;:::i;:::-;7415:39;;7473:38;7507:2;7496:9;7492:18;7473:38;:::i;:::-;7463:48;;7257:260;;;;;:::o;7522:380::-;7601:1;7597:12;;;;7644;;;7665:61;;7719:4;7711:6;7707:17;7697:27;;7665:61;7772:2;7764:6;7761:14;7741:18;7738:38;7735:161;;7818:10;7813:3;7809:20;7806:1;7799:31;7853:4;7850:1;7843:15;7881:4;7878:1;7871:15;7735:161;;7522:380;;;:::o;9190:225::-;9257:9;;;9278:11;;;9275:134;;;9331:10;9326:3;9322:20;9319:1;9312:31;9366:4;9363:1;9356:15;9394:4;9391:1;9384:15;9420:999;9849:3;9887:6;9881:13;9903:66;9962:6;9957:3;9950:4;9942:6;9938:17;9903:66;:::i;:::-;10000:6;9995:3;9991:16;9978:29;;-1:-1:-1;;;10052:2:1;10045:5;10038:17;10086:6;10080:13;10102:78;10171:8;10167:1;10160:5;10156:13;10149:4;10141:6;10137:17;10102:78;:::i;:::-;10243:1;10199:20;;10235:10;;;10228:22;10275:13;;10297:75;10275:13;10359:1;10351:10;;10344:4;10332:17;;10297:75;:::i;:::-;10392:17;10411:1;10388:25;;9420:999;-1:-1:-1;;;;;9420:999:1:o;11318:545::-;11420:2;11415:3;11412:11;11409:448;;;11456:1;11481:5;11477:2;11470:17;11526:4;11522:2;11512:19;11596:2;11584:10;11580:19;11577:1;11573:27;11567:4;11563:38;11632:4;11620:10;11617:20;11614:47;;;-1:-1:-1;11655:4:1;11614:47;11710:2;11705:3;11701:12;11698:1;11694:20;11688:4;11684:31;11674:41;;11765:82;11783:2;11776:5;11773:13;11765:82;;;11828:17;;;11809:1;11798:13;11765:82;;12039:1352;12165:3;12159:10;12192:18;12184:6;12181:30;12178:56;;;12214:18;;:::i;:::-;12243:97;12333:6;12293:38;12325:4;12319:11;12293:38;:::i;:::-;12287:4;12243:97;:::i;:::-;12395:4;;12459:2;12448:14;;12476:1;12471:663;;;;13178:1;13195:6;13192:89;;;-1:-1:-1;13247:19:1;;;13241:26;13192:89;-1:-1:-1;;11996:1:1;11992:11;;;11988:24;11984:29;11974:40;12020:1;12016:11;;;11971:57;13294:81;;12441:944;;12471:663;11265:1;11258:14;;;11302:4;11289:18;;-1:-1:-1;;12507:20:1;;;12625:236;12639:7;12636:1;12633:14;12625:236;;;12728:19;;;12722:26;12707:42;;12820:27;;;;12788:1;12776:14;;;;12655:19;;12625:236;;;12629:3;12889:6;12880:7;12877:19;12874:201;;;12950:19;;;12944:26;-1:-1:-1;;13033:1:1;13029:14;;;13045:3;13025:24;13021:37;13017:42;13002:58;12987:74;;12874:201;-1:-1:-1;;;;;13121:1:1;13105:14;;;13101:22;13088:36;;-1:-1:-1;12039:1352:1:o

Swarm Source

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