ETH Price: $3,717.47 (+4.36%)

Token

GoblinGame (GOBLIN)
 

Overview

Max Total Supply

5,586 GOBLIN

Holders

4,900

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 GOBLIN
0xa4aaea5164643420f128f34d4fdc7519567f8440
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:
GoblinGame

Compiler Version
v0.8.14+commit.80d49f37

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Unlicense license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-06-09
*/

// File: https://github.com/chiru-labs/ERC721A/blob/v4.0.0/contracts/IERC721A.sol


// ERC721A Contracts v4.0.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of an ERC721A compliant contract.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * The caller cannot approve to their own address.
     */
    error ApproveToCaller();

    /**
     * The caller cannot approve to the current owner.
     */
    error ApprovalToCurrentOwner();

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

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

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

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

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Keeps track of the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
    }

    /**
     * @dev Returns the total amount of tokens stored by the contract.
     *
     * Burned tokens are calculated here, use `_totalMinted()` if you want to count just minted tokens.
     */
    function totalSupply() external view returns (uint256);

    // ==============================
    //            IERC165
    // ==============================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // ==============================
    //            IERC721
    // ==============================

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

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

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

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

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

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

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

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

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

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

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

    // ==============================
    //        IERC721Metadata
    // ==============================

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

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: https://github.com/chiru-labs/ERC721A/blob/v4.0.0/contracts/ERC721A.sol


// ERC721A Contracts v4.0.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;


/**
 * @dev ERC721 token receiver interface.
 */
interface ERC721A__IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension. Built to optimize for lower gas during batch mints.
 *
 * Assumes serials are sequentially minted starting at _startTokenId() (defaults to 0, e.g. 0, 1, 2, 3..).
 *
 * Assumes that an owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 *
 * Assumes that the maximum token id cannot exceed 2**256 - 1 (max value of uint256).
 */
contract ERC721A is IERC721A {
    // Mask of an entry in packed address data.
    uint256 private constant BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;

    // The bit position of `numberMinted` in packed address data.
    uint256 private constant BITPOS_NUMBER_MINTED = 64;

    // The bit position of `numberBurned` in packed address data.
    uint256 private constant BITPOS_NUMBER_BURNED = 128;

    // The bit position of `aux` in packed address data.
    uint256 private constant BITPOS_AUX = 192;

    // Mask of all 256 bits in packed address data except the 64 bits for `aux`.
    uint256 private constant BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;

    // The bit position of `startTimestamp` in packed ownership.
    uint256 private constant BITPOS_START_TIMESTAMP = 160;

    // The bit mask of the `burned` bit in packed ownership.
    uint256 private constant BITMASK_BURNED = 1 << 224;
    
    // The bit position of the `nextInitialized` bit in packed ownership.
    uint256 private constant BITPOS_NEXT_INITIALIZED = 225;

    // The bit mask of the `nextInitialized` bit in packed ownership.
    uint256 private constant BITMASK_NEXT_INITIALIZED = 1 << 225;

    // The tokenId of the next token to be minted.
    uint256 private _currentIndex;

    // The number of tokens burned.
    uint256 private _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned.
    // See `_packedOwnershipOf` implementation for details.
    //
    // Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `startTimestamp`
    // - [224]      `burned`
    // - [225]      `nextInitialized`
    mapping(uint256 => uint256) private _packedOwnerships;

    // Mapping owner address to address data.
    //
    // Bits Layout:
    // - [0..63]    `balance`
    // - [64..127]  `numberMinted`
    // - [128..191] `numberBurned`
    // - [192..255] `aux`
    mapping(address => uint256) private _packedAddressData;

    // Mapping from token ID to approved address.
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

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

    /**
     * @dev Returns the starting token ID. 
     * To change the starting token ID, please override this function.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Returns the next token ID to be minted.
     */
    function _nextTokenId() internal view returns (uint256) {
        return _currentIndex;
    }

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count. 
     * To get the total number of tokens minted, please see `_totalMinted`.
     */
    function totalSupply() public view override returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than `_currentIndex - _startTokenId()` times.
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

    /**
     * @dev Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view returns (uint256) {
        // Counter underflow is impossible as _currentIndex does not decrement,
        // and it is initialized to `_startTokenId()`
        unchecked {
            return _currentIndex - _startTokenId();
        }
    }

    /**
     * @dev Returns the total number of tokens burned.
     */
    function _totalBurned() internal view returns (uint256) {
        return _burnCounter;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        // The interface IDs are constants representing the first 4 bytes of the XOR of
        // all function selectors in the interface. See: https://eips.ethereum.org/EIPS/eip-165
        // e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`
        return
            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
            interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return _packedAddressData[owner] & BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> BITPOS_NUMBER_MINTED) & BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens burned by or on behalf of `owner`.
     */
    function _numberBurned(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> BITPOS_NUMBER_BURNED) & BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
     */
    function _getAux(address owner) internal view returns (uint64) {
        return uint64(_packedAddressData[owner] >> BITPOS_AUX);
    }

    /**
     * Sets the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal {
        uint256 packed = _packedAddressData[owner];
        uint256 auxCasted;
        assembly { // Cast aux without masking.
            auxCasted := aux
        }
        packed = (packed & BITMASK_AUX_COMPLEMENT) | (auxCasted << BITPOS_AUX);
        _packedAddressData[owner] = packed;
    }

    /**
     * Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr)
                if (curr < _currentIndex) {
                    uint256 packed = _packedOwnerships[curr];
                    // If not burned.
                    if (packed & BITMASK_BURNED == 0) {
                        // Invariant:
                        // There will always be an ownership that has an address and is not burned
                        // before an ownership that does not have an address and is not burned.
                        // Hence, curr will not underflow.
                        //
                        // We can directly compare the packed value.
                        // If the address is zero, packed is zero.
                        while (packed == 0) {
                            packed = _packedOwnerships[--curr];
                        }
                        return packed;
                    }
                }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * Returns the unpacked `TokenOwnership` struct from `packed`.
     */
    function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
        ownership.addr = address(uint160(packed));
        ownership.startTimestamp = uint64(packed >> BITPOS_START_TIMESTAMP);
        ownership.burned = packed & BITMASK_BURNED != 0;
    }

    /**
     * Returns the unpacked `TokenOwnership` struct at `index`.
     */
    function _ownershipAt(uint256 index) internal view returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnerships[index]);
    }

    /**
     * @dev Initializes the ownership slot minted at `index` for efficiency purposes.
     */
    function _initializeOwnershipAt(uint256 index) internal {
        if (_packedOwnerships[index] == 0) {
            _packedOwnerships[index] = _packedOwnershipOf(index);
        }
    }

    /**
     * Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around in the collection over time.
     */
    function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnershipOf(tokenId));
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return address(uint160(_packedOwnershipOf(tokenId)));
    }

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        string memory baseURI = _baseURI();
        return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _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, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return '';
    }

    /**
     * @dev Casts the address to uint256 without masking.
     */
    function _addressToUint256(address value) private pure returns (uint256 result) {
        assembly {
            result := value
        }
    }

    /**
     * @dev Casts the boolean to uint256 without branching.
     */
    function _boolToUint256(bool value) private pure returns (uint256 result) {
        assembly {
            result := value
        }
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public override {
        address owner = address(uint160(_packedOwnershipOf(tokenId)));
        if (to == owner) revert ApprovalToCurrentOwner();

        if (_msgSenderERC721A() != owner)
            if (!isApprovedForAll(owner, _msgSenderERC721A())) {
                revert ApprovalCallerNotOwnerNorApproved();
            }

        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view override returns (address) {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        if (operator == _msgSenderERC721A()) revert ApproveToCaller();

        _operatorApprovals[_msgSenderERC721A()][operator] = approved;
        emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        _transfer(from, to, tokenId);
        if (to.code.length != 0)
            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
                revert TransferToNonERC721ReceiverImplementer();
            }
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex && // If within bounds,
            _packedOwnerships[tokenId] & BITMASK_BURNED == 0; // and not burned.
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    function _safeMint(address to, uint256 quantity) internal {
        _safeMint(to, quantity, '');
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement
     *   {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1
        // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the balance and number minted.
            _packedAddressData[to] += quantity * ((1 << BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] =
                _addressToUint256(to) |
                (block.timestamp << BITPOS_START_TIMESTAMP) |
                (_boolToUint256(quantity == 1) << BITPOS_NEXT_INITIALIZED);

            uint256 updatedIndex = startTokenId;
            uint256 end = updatedIndex + quantity;

            if (to.code.length != 0) {
                do {
                    emit Transfer(address(0), to, updatedIndex);
                    if (!_checkContractOnERC721Received(address(0), to, updatedIndex++, _data)) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (updatedIndex < end);
                // Reentrancy protection
                if (_currentIndex != startTokenId) revert();
            } else {
                do {
                    emit Transfer(address(0), to, updatedIndex++);
                } while (updatedIndex < end);
            }
            _currentIndex = updatedIndex;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 quantity) internal {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1
        // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the balance and number minted.
            _packedAddressData[to] += quantity * ((1 << BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] =
                _addressToUint256(to) |
                (block.timestamp << BITPOS_START_TIMESTAMP) |
                (_boolToUint256(quantity == 1) << BITPOS_NEXT_INITIALIZED);

            uint256 updatedIndex = startTokenId;
            uint256 end = updatedIndex + quantity;

            do {
                emit Transfer(address(0), to, updatedIndex++);
            } while (updatedIndex < end);

            _currentIndex = updatedIndex;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) private {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner();

        bool isApprovedOrOwner = (_msgSenderERC721A() == from ||
            isApprovedForAll(from, _msgSenderERC721A()) ||
            getApproved(tokenId) == _msgSenderERC721A());

        if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner.
        delete _tokenApprovals[tokenId];

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.
        unchecked {
            // We can directly increment and decrement the balances.
            --_packedAddressData[from]; // Updates: `balance -= 1`.
            ++_packedAddressData[to]; // Updates: `balance += 1`.

            // Updates:
            // - `address` to the next owner.
            // - `startTimestamp` to the timestamp of transfering.
            // - `burned` to `false`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] =
                _addressToUint256(to) |
                (block.timestamp << BITPOS_START_TIMESTAMP) |
                BITMASK_NEXT_INITIALIZED;

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Equivalent to `_burn(tokenId, false)`.
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        address from = address(uint160(prevOwnershipPacked));

        if (approvalCheck) {
            bool isApprovedOrOwner = (_msgSenderERC721A() == from ||
                isApprovedForAll(from, _msgSenderERC721A()) ||
                getApproved(tokenId) == _msgSenderERC721A());

            if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        }

        _beforeTokenTransfers(from, address(0), tokenId, 1);

        // Clear approvals from the previous owner.
        delete _tokenApprovals[tokenId];

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.
        unchecked {
            // Updates:
            // - `balance -= 1`.
            // - `numberBurned += 1`.
            //
            // We can directly decrement the balance, and increment the number burned.
            // This is equivalent to `packed -= 1; packed += 1 << BITPOS_NUMBER_BURNED;`.
            _packedAddressData[from] += (1 << BITPOS_NUMBER_BURNED) - 1;

            // Updates:
            // - `address` to the last owner.
            // - `startTimestamp` to the timestamp of burning.
            // - `burned` to `true`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] =
                _addressToUint256(from) |
                (block.timestamp << BITPOS_START_TIMESTAMP) |
                BITMASK_BURNED | 
                BITMASK_NEXT_INITIALIZED;

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, address(0), tokenId);
        _afterTokenTransfers(from, address(0), tokenId, 1);

        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
        unchecked {
            _burnCounter++;
        }
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
            bytes4 retval
        ) {
            return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes
     * minting.
     * And also called after one token has been burned.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Returns the message sender (defaults to `msg.sender`).
     *
     * If you are writing GSN compatible contracts, you need to override this function.
     */
    function _msgSenderERC721A() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function _toString(uint256 value) internal pure returns (string memory ptr) {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), 
            // but we allocate 128 bytes to keep the free memory pointer 32-byte word aliged.
            // We will need 1 32-byte word to store the length, 
            // and 3 32-byte words to store a maximum of 78 digits. Total: 32 + 3 * 32 = 128.
            ptr := add(mload(0x40), 128)
            // Update the free memory pointer to allocate.
            mstore(0x40, ptr)

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

            // We write the string from the rightmost digit to the leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // Costs a bit more than early returning for the zero case,
            // but cheaper in terms of deployment and overall runtime costs.
            for { 
                // Initialize and perform the first pass without check.
                let temp := value
                // Move the pointer 1 byte leftwards to point to an empty character slot.
                ptr := sub(ptr, 1)
                // Write the character to the pointer. 48 is the ASCII index of '0'.
                mstore8(ptr, add(48, mod(temp, 10)))
                temp := div(temp, 10)
            } temp { 
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
            } { // Body of the for loop.
                ptr := sub(ptr, 1)
                mstore8(ptr, add(48, mod(temp, 10)))
            }
            
            let length := sub(end, ptr)
            // Move the pointer 32 bytes leftwards to make room for the length.
            ptr := sub(ptr, 32)
            // Store the length.
            mstore(ptr, length)
        }
    }
}

// File: https://github.com/chiru-labs/ERC721A/blob/v4.0.0/contracts/extensions/IERC721AQueryable.sol


// ERC721A Contracts v4.0.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;


/**
 * @dev Interface of an ERC721AQueryable compliant contract.
 */
interface IERC721AQueryable is IERC721A {
    /**
     * Invalid query range (`start` >= `stop`).
     */
    error InvalidQueryRange();

    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *   - `addr` = `address(0)`
     *   - `startTimestamp` = `0`
     *   - `burned` = `false`
     *
     * If the `tokenId` is burned:
     *   - `addr` = `<Address of owner before token was burned>`
     *   - `startTimestamp` = `<Timestamp when token was burned>`
     *   - `burned = `true`
     *
     * Otherwise:
     *   - `addr` = `<Address of owner>`
     *   - `startTimestamp` = `<Timestamp of start of ownership>`
     *   - `burned = `false`
     */
    function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory);

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start` < `stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view returns (uint256[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(totalSupply) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K pfp collections should be fine).
     */
    function tokensOfOwner(address owner) external view returns (uint256[] memory);
}

// File: https://github.com/chiru-labs/ERC721A/blob/v4.0.0/contracts/extensions/ERC721AQueryable.sol


// ERC721A Contracts v4.0.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;



/**
 * @title ERC721A Queryable
 * @dev ERC721A subclass with convenience query functions.
 */
abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable {
    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *   - `addr` = `address(0)`
     *   - `startTimestamp` = `0`
     *   - `burned` = `false`
     *
     * If the `tokenId` is burned:
     *   - `addr` = `<Address of owner before token was burned>`
     *   - `startTimestamp` = `<Timestamp when token was burned>`
     *   - `burned = `true`
     *
     * Otherwise:
     *   - `addr` = `<Address of owner>`
     *   - `startTimestamp` = `<Timestamp of start of ownership>`
     *   - `burned = `false`
     */
    function explicitOwnershipOf(uint256 tokenId) public view override returns (TokenOwnership memory) {
        TokenOwnership memory ownership;
        if (tokenId < _startTokenId() || tokenId >= _nextTokenId()) {
            return ownership;
        }
        ownership = _ownershipAt(tokenId);
        if (ownership.burned) {
            return ownership;
        }
        return _ownershipOf(tokenId);
    }

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] memory tokenIds) external view override returns (TokenOwnership[] memory) {
        unchecked {
            uint256 tokenIdsLength = tokenIds.length;
            TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength);
            for (uint256 i; i != tokenIdsLength; ++i) {
                ownerships[i] = explicitOwnershipOf(tokenIds[i]);
            }
            return ownerships;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start` < `stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view override returns (uint256[] memory) {
        unchecked {
            if (start >= stop) revert InvalidQueryRange();
            uint256 tokenIdsIdx;
            uint256 stopLimit = _nextTokenId();
            // Set `start = max(start, _startTokenId())`.
            if (start < _startTokenId()) {
                start = _startTokenId();
            }
            // Set `stop = min(stop, stopLimit)`.
            if (stop > stopLimit) {
                stop = stopLimit;
            }
            uint256 tokenIdsMaxLength = balanceOf(owner);
            // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`,
            // to cater for cases where `balanceOf(owner)` is too big.
            if (start < stop) {
                uint256 rangeLength = stop - start;
                if (rangeLength < tokenIdsMaxLength) {
                    tokenIdsMaxLength = rangeLength;
                }
            } else {
                tokenIdsMaxLength = 0;
            }
            uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength);
            if (tokenIdsMaxLength == 0) {
                return tokenIds;
            }
            // We need to call `explicitOwnershipOf(start)`,
            // because the slot at `start` may not be initialized.
            TokenOwnership memory ownership = explicitOwnershipOf(start);
            address currOwnershipAddr;
            // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`.
            // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range.
            if (!ownership.burned) {
                currOwnershipAddr = ownership.addr;
            }
            for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) {
                ownership = _ownershipAt(i);
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            // Downsize the array to fit.
            assembly {
                mstore(tokenIds, tokenIdsIdx)
            }
            return tokenIds;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(totalSupply) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K pfp collections should be fine).
     */
    function tokensOfOwner(address owner) external view override returns (uint256[] memory) {
        unchecked {
            uint256 tokenIdsIdx;
            address currOwnershipAddr;
            uint256 tokenIdsLength = balanceOf(owner);
            uint256[] memory tokenIds = new uint256[](tokenIdsLength);
            TokenOwnership memory ownership;
            for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) {
                ownership = _ownershipAt(i);
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            return tokenIds;
        }
    }
}

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


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

pragma solidity ^0.8.0;

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

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

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

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

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

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

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


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

pragma solidity ^0.8.0;

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

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

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

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

// File: GoblinGame.sol


pragma solidity 0.8.14;




interface IDuel {
    function isDead(uint256 id) external view returns (bool);

    function tokenTiers(uint256 id) external view returns (uint256);
}

contract GoblinGame is ERC721AQueryable, Ownable {
    IDuel public duel;

    string internal _baseTokenURI;
    string internal _unrevealedURI;

    uint256 internal _reserved;

    bool public revealed;
    bool public mintActive;

    mapping(address => bool) public minted;

    uint256 public constant MAX_RESERVED_AMOUNT = 500;
    uint256 public constant MAX_TOTAL_SUPPLY = 9999;

    constructor(string memory unrevealedURI) ERC721A("GoblinGame", "GOBLIN") {
        _unrevealedURI = unrevealedURI;
    }

    // URI FUNCTIONS

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

    function tokenURI(uint256 tokenId) public view virtual override(IERC721A, ERC721A) returns (string memory) {
        if (!revealed) {
            return _unrevealedURI;
        }

        string memory baseURI = _baseURI();
        if (address(duel) == address(0)) {
            return string(abi.encodePacked(baseURI, _toString(tokenId), "-0"));
        }

        if (duel.isDead(tokenId)) {
            return _unrevealedURI;
        }

        uint256 level = duel.tokenTiers(tokenId);
        return string(abi.encodePacked(baseURI, _toString(tokenId), "-", _toString(level)));
    }

    // OWNER FUNCTIONS

    function setBaseURI(string calldata baseURI) external onlyOwner {
        _baseTokenURI = baseURI;
    }

    function setUnrevealedURI(string calldata unrevealedURI) external onlyOwner {
        _unrevealedURI = unrevealedURI;
    }

    function setDuel(address _duel) external onlyOwner {
        duel = IDuel(_duel);
    }

    function flipMintStatus() public onlyOwner {
        mintActive = !mintActive;
    }

    function flipReveal() public onlyOwner {
        revealed = !revealed;
    }

    function withdraw() external onlyOwner {
        (bool success, ) = msg.sender.call{value: address(this).balance}("");
        require(success, "Withdraw failed");
    }

    // MINTING FUNCTIONS

    function mint() external payable {
        require(mintActive, "Public mint not active");
        require(msg.sender == tx.origin, "Caller not allowed");
        require(!minted[msg.sender], "Wallet already minted one");
        require(totalSupply() < MAX_TOTAL_SUPPLY, "Would exceed max supply");

        _safeMint(msg.sender, 1);
        minted[msg.sender] = true;
    }

    // reserves 'amount' NFTs minted directly to a specified wallet
    function reserve(address to, uint256 amount) external onlyOwner {
        require(_reserved + amount <= MAX_RESERVED_AMOUNT, "Would exceed max reserved amount");
        require(amount + totalSupply() <= MAX_TOTAL_SUPPLY, "Would exceed max supply");
        
        _safeMint(to, amount);
        _reserved += amount;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"unrevealedURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","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":"approved","type":"bool"}],"name":"ApprovalForAll","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":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_RESERVED_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOTAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duel","outputs":[{"internalType":"contract IDuel","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"}],"internalType":"struct IERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"}],"internalType":"struct IERC721A.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flipMintStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","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":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"reserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_duel","type":"address"}],"name":"setDuel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"unrevealedURI","type":"string"}],"name":"setUnrevealedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162002624380380620026248339810160408190526200003491620001d7565b604080518082018252600a815269476f626c696e47616d6560b01b60208083019182528351808501909452600684526523a7a12624a760d11b90840152815191929162000084916002916200011b565b5080516200009a9060039060208401906200011b565b50506000805550620000ac33620000c9565b8051620000c190600b9060208401906200011b565b5050620002ef565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8280546200012990620002b3565b90600052602060002090601f0160209004810192826200014d576000855562000198565b82601f106200016857805160ff191683800117855562000198565b8280016001018555821562000198579182015b82811115620001985782518255916020019190600101906200017b565b50620001a6929150620001aa565b5090565b5b80821115620001a65760008155600101620001ab565b634e487b7160e01b600052604160045260246000fd5b60006020808385031215620001eb57600080fd5b82516001600160401b03808211156200020357600080fd5b818501915085601f8301126200021857600080fd5b8151818111156200022d576200022d620001c1565b604051601f8201601f19908116603f01168101908382118183101715620002585762000258620001c1565b8160405282815288868487010111156200027157600080fd5b600093505b8284101562000295578484018601518185018701529285019262000276565b82841115620002a75760008684830101525b98975050505050505050565b600181811c90821680620002c857607f821691505b602082108103620002e957634e487b7160e01b600052602260045260246000fd5b50919050565b61232580620002ff6000396000f3fe6080604052600436106102045760003560e01c806370a0823111610118578063b01ee427116100a0578063cc47a40b1161006f578063cc47a40b146105d2578063e985e9c5146105f2578063f09f18e314610612578063f2fde38b14610628578063fe2c7fee1461064857600080fd5b8063b01ee42714610550578063b88d4fde14610565578063c23dc68f14610585578063c87b56dd146105b257600080fd5b80638ba5cb85116100e75780638ba5cb85146104bd5780638da5cb5b146104dd57806395d89b41146104fb57806399a2557a14610510578063a22cb4651461053057600080fd5b806370a082311461043b578063715018a61461045b57806372fd0a58146104705780638462151c1461049057600080fd5b806325fd90f31161019b57806342842e0e1161016a57806342842e0e1461039457806351830227146103b457806355f804b3146103ce5780635bbb2177146103ee5780636352211e1461041b57600080fd5b806325fd90f31461033557806333039d3d146103545780633b84d9c61461036a5780633ccfd60b1461037f57600080fd5b80631249c58b116101d75780631249c58b146102ba57806318160ddd146102c25780631e7269c5146102e557806323b872dd1461031557600080fd5b806301ffc9a71461020957806306fdde031461023e578063081812fc14610260578063095ea7b314610298575b600080fd5b34801561021557600080fd5b50610229610224366004611c47565b610668565b60405190151581526020015b60405180910390f35b34801561024a57600080fd5b506102536106ba565b6040516102359190611cbc565b34801561026c57600080fd5b5061028061027b366004611ccf565b61074c565b6040516001600160a01b039091168152602001610235565b3480156102a457600080fd5b506102b86102b3366004611d04565b610790565b005b6102b8610862565b3480156102ce57600080fd5b50600154600054035b604051908152602001610235565b3480156102f157600080fd5b50610229610300366004611d2e565b600e6020526000908152604090205460ff1681565b34801561032157600080fd5b506102b8610330366004611d49565b6109d9565b34801561034157600080fd5b50600d5461022990610100900460ff1681565b34801561036057600080fd5b506102d761270f81565b34801561037657600080fd5b506102b86109e9565b34801561038b57600080fd5b506102b8610a27565b3480156103a057600080fd5b506102b86103af366004611d49565b610ade565b3480156103c057600080fd5b50600d546102299060ff1681565b3480156103da57600080fd5b506102b86103e9366004611d85565b610af9565b3480156103fa57600080fd5b5061040e610409366004611e3e565b610b2f565b6040516102359190611ee4565b34801561042757600080fd5b50610280610436366004611ccf565b610bf6565b34801561044757600080fd5b506102d7610456366004611d2e565b610c01565b34801561046757600080fd5b506102b8610c50565b34801561047c57600080fd5b50600954610280906001600160a01b031681565b34801561049c57600080fd5b506104b06104ab366004611d2e565b610c86565b6040516102359190611f4f565b3480156104c957600080fd5b506102b86104d8366004611d2e565b610d88565b3480156104e957600080fd5b506008546001600160a01b0316610280565b34801561050757600080fd5b50610253610dd4565b34801561051c57600080fd5b506104b061052b366004611f87565b610de3565b34801561053c57600080fd5b506102b861054b366004611fc8565b610f5d565b34801561055c57600080fd5b506102b8610ff2565b34801561057157600080fd5b506102b8610580366004611fff565b611039565b34801561059157600080fd5b506105a56105a0366004611ccf565b611083565b60405161023591906120bf565b3480156105be57600080fd5b506102536105cd366004611ccf565b6110ec565b3480156105de57600080fd5b506102b86105ed366004611d04565b61138c565b3480156105fe57600080fd5b5061022961060d3660046120f5565b61149c565b34801561061e57600080fd5b506102d76101f481565b34801561063457600080fd5b506102b8610643366004611d2e565b6114ca565b34801561065457600080fd5b506102b8610663366004611d85565b611562565b60006301ffc9a760e01b6001600160e01b03198316148061069957506380ac58cd60e01b6001600160e01b03198316145b806106b45750635b5e139f60e01b6001600160e01b03198316145b92915050565b6060600280546106c990612128565b80601f01602080910402602001604051908101604052809291908181526020018280546106f590612128565b80156107425780601f1061071757610100808354040283529160200191610742565b820191906000526020600020905b81548152906001019060200180831161072557829003601f168201915b5050505050905090565b600061075782611598565b610774576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b600061079b826115bf565b9050806001600160a01b0316836001600160a01b0316036107cf5760405163250fdee360e21b815260040160405180910390fd5b336001600160a01b03821614610806576107e9813361149c565b610806576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600d54610100900460ff166108b75760405162461bcd60e51b81526020600482015260166024820152755075626c6963206d696e74206e6f742061637469766560501b60448201526064015b60405180910390fd5b3332146108fb5760405162461bcd60e51b815260206004820152601260248201527110d85b1b195c881b9bdd08185b1b1bddd95960721b60448201526064016108ae565b336000908152600e602052604090205460ff161561095b5760405162461bcd60e51b815260206004820152601960248201527f57616c6c657420616c7265616479206d696e746564206f6e650000000000000060448201526064016108ae565b61270f61096b6001546000540390565b106109b25760405162461bcd60e51b8152602060048201526017602482015276576f756c6420657863656564206d617820737570706c7960481b60448201526064016108ae565b6109bd336001611626565b336000908152600e60205260409020805460ff19166001179055565b6109e4838383611644565b505050565b6008546001600160a01b03163314610a135760405162461bcd60e51b81526004016108ae90612162565b600d805460ff19811660ff90911615179055565b6008546001600160a01b03163314610a515760405162461bcd60e51b81526004016108ae90612162565b604051600090339047908381818185875af1925050503d8060008114610a93576040519150601f19603f3d011682016040523d82523d6000602084013e610a98565b606091505b5050905080610adb5760405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b60448201526064016108ae565b50565b6109e483838360405180602001604052806000815250611039565b6008546001600160a01b03163314610b235760405162461bcd60e51b81526004016108ae90612162565b6109e4600a8383611b98565b805160609060008167ffffffffffffffff811115610b4f57610b4f611df7565b604051908082528060200260200182016040528015610b9a57816020015b6040805160608101825260008082526020808301829052928201528252600019909201910181610b6d5790505b50905060005b828114610bee57610bc9858281518110610bbc57610bbc612197565b6020026020010151611083565b828281518110610bdb57610bdb612197565b6020908102919091010152600101610ba0565b509392505050565b60006106b4826115bf565b60006001600160a01b038216610c2a576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526005602052604090205467ffffffffffffffff1690565b6008546001600160a01b03163314610c7a5760405162461bcd60e51b81526004016108ae90612162565b610c8460006117eb565b565b60606000806000610c9685610c01565b905060008167ffffffffffffffff811115610cb357610cb3611df7565b604051908082528060200260200182016040528015610cdc578160200160208202803683370190505b509050610d02604080516060810182526000808252602082018190529181019190915290565b60005b838614610d7c57610d158161183d565b91508160400151610d745781516001600160a01b031615610d3557815194505b876001600160a01b0316856001600160a01b031603610d745780838780600101985081518110610d6757610d67612197565b6020026020010181815250505b600101610d05565b50909695505050505050565b6008546001600160a01b03163314610db25760405162461bcd60e51b81526004016108ae90612162565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6060600380546106c990612128565b6060818310610e0557604051631960ccad60e11b815260040160405180910390fd5b600080610e1160005490565b905080841115610e1f578093505b6000610e2a87610c01565b905084861015610e495785850381811015610e43578091505b50610e4d565b5060005b60008167ffffffffffffffff811115610e6857610e68611df7565b604051908082528060200260200182016040528015610e91578160200160208202803683370190505b50905081600003610ea7579350610f5692505050565b6000610eb288611083565b905060008160400151610ec3575080515b885b888114158015610ed55750848714155b15610f4a57610ee38161183d565b92508260400151610f425782516001600160a01b031615610f0357825191505b8a6001600160a01b0316826001600160a01b031603610f425780848880600101995081518110610f3557610f35612197565b6020026020010181815250505b600101610ec5565b50505092835250909150505b9392505050565b336001600160a01b03831603610f865760405163b06307db60e01b815260040160405180910390fd5b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6008546001600160a01b0316331461101c5760405162461bcd60e51b81526004016108ae90612162565b600d805461ff001981166101009182900460ff1615909102179055565b611044848484611644565b6001600160a01b0383163b1561107d5761106084848484611872565b61107d576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b60408051606080820183526000808352602080840182905283850182905284519283018552818352820181905292810183905290915060005483106110c85792915050565b6110d18361183d565b90508060400151156110e35792915050565b610f568361195d565b600d5460609060ff1661118b57600b805461110690612128565b80601f016020809104026020016040519081016040528092919081815260200182805461113290612128565b801561117f5780601f106111545761010080835404028352916020019161117f565b820191906000526020600020905b81548152906001019060200180831161116257829003601f168201915b50505050509050919050565b600061119561198b565b6009549091506001600160a01b03166111da57806111b28461199a565b6040516020016111c39291906121ad565b604051602081830303815290604052915050919050565b6009546040516316fec7ff60e11b8152600481018590526001600160a01b0390911690632dfd8ffe90602401602060405180830381865afa158015611223573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124791906121e9565b156112df57600b805461125990612128565b80601f016020809104026020016040519081016040528092919081815260200182805461128590612128565b80156112d25780601f106112a7576101008083540402835291602001916112d2565b820191906000526020600020905b8154815290600101906020018083116112b557829003601f168201915b5050505050915050919050565b6009546040516340c7972160e11b8152600481018590526000916001600160a01b03169063818f2e4290602401602060405180830381865afa158015611329573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134d9190612206565b9050816113598561199a565b6113628361199a565b6040516020016113749392919061221f565b60405160208183030381529060405292505050919050565b6008546001600160a01b031633146113b65760405162461bcd60e51b81526004016108ae90612162565b6101f481600c546113c7919061226f565b11156114155760405162461bcd60e51b815260206004820181905260248201527f576f756c6420657863656564206d617820726573657276656420616d6f756e7460448201526064016108ae565b61270f6114256001546000540390565b61142f908361226f565b11156114775760405162461bcd60e51b8152602060048201526017602482015276576f756c6420657863656564206d617820737570706c7960481b60448201526064016108ae565b6114818282611626565b80600c6000828254611493919061226f565b90915550505050565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b6008546001600160a01b031633146114f45760405162461bcd60e51b81526004016108ae90612162565b6001600160a01b0381166115595760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108ae565b610adb816117eb565b6008546001600160a01b0316331461158c5760405162461bcd60e51b81526004016108ae90612162565b6109e4600b8383611b98565b60008054821080156106b4575050600090815260046020526040902054600160e01b161590565b60008160005481101561160d5760008181526004602052604081205490600160e01b8216900361160b575b80600003610f565750600019016000818152600460205260409020546115ea565b505b604051636f96cda160e11b815260040160405180910390fd5b6116408282604051806020016040528060008152506119e9565b5050565b600061164f826115bf565b9050836001600160a01b0316816001600160a01b0316146116825760405162a1148160e81b815260040160405180910390fd5b6000336001600160a01b03861614806116a057506116a0853361149c565b806116bb5750336116b08461074c565b6001600160a01b0316145b9050806116db57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b03841661170257604051633a954ecd60e21b815260040160405180910390fd5b600083815260066020908152604080832080546001600160a01b03191690556001600160a01b038881168452600583528184208054600019019055871683528083208054600101905585835260049091528120600160e11b4260a01b87178117909155831690036117a3576001830160008181526004602052604081205490036117a15760005481146117a15760008181526004602052604090208390555b505b82846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60408051606081018252600080825260208201819052918101919091526000828152600460205260409020546106b490611b5d565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906118a7903390899088908890600401612295565b6020604051808303816000875af19250505080156118e2575060408051601f3d908101601f191682019092526118df918101906122d2565b60015b611940573d808015611910576040519150601f19603f3d011682016040523d82523d6000602084013e611915565b606091505b508051600003611938576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b60408051606081018252600080825260208201819052918101919091526106b4611986836115bf565b611b5d565b6060600a80546106c990612128565b604080516080810191829052607f0190826030600a8206018353600a90045b80156119d757600183039250600a81066030018353600a90046119b9565b50819003601f19909101908152919050565b6000546001600160a01b038416611a1257604051622e076360e81b815260040160405180910390fd5b82600003611a335760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03841660008181526005602090815260408083208054680100000000000000018902019055848352600490915290204260a01b86176001861460e11b1790558190818501903b15611b08575b60405182906001600160a01b038816906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4611ad16000878480600101955087611872565b611aee576040516368d2bf6b60e11b815260040160405180910390fd5b808210611a86578260005414611b0357600080fd5b611b4d565b5b6040516001830192906001600160a01b038816906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4808210611b09575b50600090815561107d9085838684565b604080516060810182526001600160a01b038316815260a083901c67ffffffffffffffff166020820152600160e01b90921615159082015290565b828054611ba490612128565b90600052602060002090601f016020900481019282611bc65760008555611c0c565b82601f10611bdf5782800160ff19823516178555611c0c565b82800160010185558215611c0c579182015b82811115611c0c578235825591602001919060010190611bf1565b50611c18929150611c1c565b5090565b5b80821115611c185760008155600101611c1d565b6001600160e01b031981168114610adb57600080fd5b600060208284031215611c5957600080fd5b8135610f5681611c31565b60005b83811015611c7f578181015183820152602001611c67565b8381111561107d5750506000910152565b60008151808452611ca8816020860160208601611c64565b601f01601f19169290920160200192915050565b602081526000610f566020830184611c90565b600060208284031215611ce157600080fd5b5035919050565b80356001600160a01b0381168114611cff57600080fd5b919050565b60008060408385031215611d1757600080fd5b611d2083611ce8565b946020939093013593505050565b600060208284031215611d4057600080fd5b610f5682611ce8565b600080600060608486031215611d5e57600080fd5b611d6784611ce8565b9250611d7560208501611ce8565b9150604084013590509250925092565b60008060208385031215611d9857600080fd5b823567ffffffffffffffff80821115611db057600080fd5b818501915085601f830112611dc457600080fd5b813581811115611dd357600080fd5b866020828501011115611de557600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611e3657611e36611df7565b604052919050565b60006020808385031215611e5157600080fd5b823567ffffffffffffffff80821115611e6957600080fd5b818501915085601f830112611e7d57600080fd5b813581811115611e8f57611e8f611df7565b8060051b9150611ea0848301611e0d565b8181529183018401918481019088841115611eba57600080fd5b938501935b83851015611ed857843582529385019390850190611ebf565b98975050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015610d7c57611f3c83855180516001600160a01b0316825260208082015167ffffffffffffffff16908301526040908101511515910152565b9284019260609290920191600101611f00565b6020808252825182820181905260009190848201906040850190845b81811015610d7c57835183529284019291840191600101611f6b565b600080600060608486031215611f9c57600080fd5b611fa584611ce8565b95602085013595506040909401359392505050565b8015158114610adb57600080fd5b60008060408385031215611fdb57600080fd5b611fe483611ce8565b91506020830135611ff481611fba565b809150509250929050565b6000806000806080858703121561201557600080fd5b61201e85611ce8565b9350602061202d818701611ce8565b935060408601359250606086013567ffffffffffffffff8082111561205157600080fd5b818801915088601f83011261206557600080fd5b81358181111561207757612077611df7565b612089601f8201601f19168501611e0d565b9150808252898482850101111561209f57600080fd5b808484018584013760008482840101525080935050505092959194509250565b81516001600160a01b0316815260208083015167ffffffffffffffff1690820152604080830151151590820152606081016106b4565b6000806040838503121561210857600080fd5b61211183611ce8565b915061211f60208401611ce8565b90509250929050565b600181811c9082168061213c57607f821691505b60208210810361215c57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600083516121bf818460208801611c64565b8351908301906121d3818360208801611c64565b6102d360f41b9101908152600201949350505050565b6000602082840312156121fb57600080fd5b8151610f5681611fba565b60006020828403121561221857600080fd5b5051919050565b60008451612231818460208901611c64565b845190830190612245818360208901611c64565b602d60f81b91019081528351612262816001840160208801611c64565b0160010195945050505050565b6000821982111561229057634e487b7160e01b600052601160045260246000fd5b500190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906122c890830184611c90565b9695505050505050565b6000602082840312156122e457600080fd5b8151610f5681611c3156fea2646970667358221220057de6761a44e35c9ed6f88351790da909e790b057f33b79dc57d378a6099edc64736f6c634300080e003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d5457463552686933336f6172377a6f74334572757354364c6d37713836556a3568547357694539764a4770590000000000000000000000

Deployed Bytecode

0x6080604052600436106102045760003560e01c806370a0823111610118578063b01ee427116100a0578063cc47a40b1161006f578063cc47a40b146105d2578063e985e9c5146105f2578063f09f18e314610612578063f2fde38b14610628578063fe2c7fee1461064857600080fd5b8063b01ee42714610550578063b88d4fde14610565578063c23dc68f14610585578063c87b56dd146105b257600080fd5b80638ba5cb85116100e75780638ba5cb85146104bd5780638da5cb5b146104dd57806395d89b41146104fb57806399a2557a14610510578063a22cb4651461053057600080fd5b806370a082311461043b578063715018a61461045b57806372fd0a58146104705780638462151c1461049057600080fd5b806325fd90f31161019b57806342842e0e1161016a57806342842e0e1461039457806351830227146103b457806355f804b3146103ce5780635bbb2177146103ee5780636352211e1461041b57600080fd5b806325fd90f31461033557806333039d3d146103545780633b84d9c61461036a5780633ccfd60b1461037f57600080fd5b80631249c58b116101d75780631249c58b146102ba57806318160ddd146102c25780631e7269c5146102e557806323b872dd1461031557600080fd5b806301ffc9a71461020957806306fdde031461023e578063081812fc14610260578063095ea7b314610298575b600080fd5b34801561021557600080fd5b50610229610224366004611c47565b610668565b60405190151581526020015b60405180910390f35b34801561024a57600080fd5b506102536106ba565b6040516102359190611cbc565b34801561026c57600080fd5b5061028061027b366004611ccf565b61074c565b6040516001600160a01b039091168152602001610235565b3480156102a457600080fd5b506102b86102b3366004611d04565b610790565b005b6102b8610862565b3480156102ce57600080fd5b50600154600054035b604051908152602001610235565b3480156102f157600080fd5b50610229610300366004611d2e565b600e6020526000908152604090205460ff1681565b34801561032157600080fd5b506102b8610330366004611d49565b6109d9565b34801561034157600080fd5b50600d5461022990610100900460ff1681565b34801561036057600080fd5b506102d761270f81565b34801561037657600080fd5b506102b86109e9565b34801561038b57600080fd5b506102b8610a27565b3480156103a057600080fd5b506102b86103af366004611d49565b610ade565b3480156103c057600080fd5b50600d546102299060ff1681565b3480156103da57600080fd5b506102b86103e9366004611d85565b610af9565b3480156103fa57600080fd5b5061040e610409366004611e3e565b610b2f565b6040516102359190611ee4565b34801561042757600080fd5b50610280610436366004611ccf565b610bf6565b34801561044757600080fd5b506102d7610456366004611d2e565b610c01565b34801561046757600080fd5b506102b8610c50565b34801561047c57600080fd5b50600954610280906001600160a01b031681565b34801561049c57600080fd5b506104b06104ab366004611d2e565b610c86565b6040516102359190611f4f565b3480156104c957600080fd5b506102b86104d8366004611d2e565b610d88565b3480156104e957600080fd5b506008546001600160a01b0316610280565b34801561050757600080fd5b50610253610dd4565b34801561051c57600080fd5b506104b061052b366004611f87565b610de3565b34801561053c57600080fd5b506102b861054b366004611fc8565b610f5d565b34801561055c57600080fd5b506102b8610ff2565b34801561057157600080fd5b506102b8610580366004611fff565b611039565b34801561059157600080fd5b506105a56105a0366004611ccf565b611083565b60405161023591906120bf565b3480156105be57600080fd5b506102536105cd366004611ccf565b6110ec565b3480156105de57600080fd5b506102b86105ed366004611d04565b61138c565b3480156105fe57600080fd5b5061022961060d3660046120f5565b61149c565b34801561061e57600080fd5b506102d76101f481565b34801561063457600080fd5b506102b8610643366004611d2e565b6114ca565b34801561065457600080fd5b506102b8610663366004611d85565b611562565b60006301ffc9a760e01b6001600160e01b03198316148061069957506380ac58cd60e01b6001600160e01b03198316145b806106b45750635b5e139f60e01b6001600160e01b03198316145b92915050565b6060600280546106c990612128565b80601f01602080910402602001604051908101604052809291908181526020018280546106f590612128565b80156107425780601f1061071757610100808354040283529160200191610742565b820191906000526020600020905b81548152906001019060200180831161072557829003601f168201915b5050505050905090565b600061075782611598565b610774576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b600061079b826115bf565b9050806001600160a01b0316836001600160a01b0316036107cf5760405163250fdee360e21b815260040160405180910390fd5b336001600160a01b03821614610806576107e9813361149c565b610806576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600d54610100900460ff166108b75760405162461bcd60e51b81526020600482015260166024820152755075626c6963206d696e74206e6f742061637469766560501b60448201526064015b60405180910390fd5b3332146108fb5760405162461bcd60e51b815260206004820152601260248201527110d85b1b195c881b9bdd08185b1b1bddd95960721b60448201526064016108ae565b336000908152600e602052604090205460ff161561095b5760405162461bcd60e51b815260206004820152601960248201527f57616c6c657420616c7265616479206d696e746564206f6e650000000000000060448201526064016108ae565b61270f61096b6001546000540390565b106109b25760405162461bcd60e51b8152602060048201526017602482015276576f756c6420657863656564206d617820737570706c7960481b60448201526064016108ae565b6109bd336001611626565b336000908152600e60205260409020805460ff19166001179055565b6109e4838383611644565b505050565b6008546001600160a01b03163314610a135760405162461bcd60e51b81526004016108ae90612162565b600d805460ff19811660ff90911615179055565b6008546001600160a01b03163314610a515760405162461bcd60e51b81526004016108ae90612162565b604051600090339047908381818185875af1925050503d8060008114610a93576040519150601f19603f3d011682016040523d82523d6000602084013e610a98565b606091505b5050905080610adb5760405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b60448201526064016108ae565b50565b6109e483838360405180602001604052806000815250611039565b6008546001600160a01b03163314610b235760405162461bcd60e51b81526004016108ae90612162565b6109e4600a8383611b98565b805160609060008167ffffffffffffffff811115610b4f57610b4f611df7565b604051908082528060200260200182016040528015610b9a57816020015b6040805160608101825260008082526020808301829052928201528252600019909201910181610b6d5790505b50905060005b828114610bee57610bc9858281518110610bbc57610bbc612197565b6020026020010151611083565b828281518110610bdb57610bdb612197565b6020908102919091010152600101610ba0565b509392505050565b60006106b4826115bf565b60006001600160a01b038216610c2a576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526005602052604090205467ffffffffffffffff1690565b6008546001600160a01b03163314610c7a5760405162461bcd60e51b81526004016108ae90612162565b610c8460006117eb565b565b60606000806000610c9685610c01565b905060008167ffffffffffffffff811115610cb357610cb3611df7565b604051908082528060200260200182016040528015610cdc578160200160208202803683370190505b509050610d02604080516060810182526000808252602082018190529181019190915290565b60005b838614610d7c57610d158161183d565b91508160400151610d745781516001600160a01b031615610d3557815194505b876001600160a01b0316856001600160a01b031603610d745780838780600101985081518110610d6757610d67612197565b6020026020010181815250505b600101610d05565b50909695505050505050565b6008546001600160a01b03163314610db25760405162461bcd60e51b81526004016108ae90612162565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6060600380546106c990612128565b6060818310610e0557604051631960ccad60e11b815260040160405180910390fd5b600080610e1160005490565b905080841115610e1f578093505b6000610e2a87610c01565b905084861015610e495785850381811015610e43578091505b50610e4d565b5060005b60008167ffffffffffffffff811115610e6857610e68611df7565b604051908082528060200260200182016040528015610e91578160200160208202803683370190505b50905081600003610ea7579350610f5692505050565b6000610eb288611083565b905060008160400151610ec3575080515b885b888114158015610ed55750848714155b15610f4a57610ee38161183d565b92508260400151610f425782516001600160a01b031615610f0357825191505b8a6001600160a01b0316826001600160a01b031603610f425780848880600101995081518110610f3557610f35612197565b6020026020010181815250505b600101610ec5565b50505092835250909150505b9392505050565b336001600160a01b03831603610f865760405163b06307db60e01b815260040160405180910390fd5b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6008546001600160a01b0316331461101c5760405162461bcd60e51b81526004016108ae90612162565b600d805461ff001981166101009182900460ff1615909102179055565b611044848484611644565b6001600160a01b0383163b1561107d5761106084848484611872565b61107d576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b60408051606080820183526000808352602080840182905283850182905284519283018552818352820181905292810183905290915060005483106110c85792915050565b6110d18361183d565b90508060400151156110e35792915050565b610f568361195d565b600d5460609060ff1661118b57600b805461110690612128565b80601f016020809104026020016040519081016040528092919081815260200182805461113290612128565b801561117f5780601f106111545761010080835404028352916020019161117f565b820191906000526020600020905b81548152906001019060200180831161116257829003601f168201915b50505050509050919050565b600061119561198b565b6009549091506001600160a01b03166111da57806111b28461199a565b6040516020016111c39291906121ad565b604051602081830303815290604052915050919050565b6009546040516316fec7ff60e11b8152600481018590526001600160a01b0390911690632dfd8ffe90602401602060405180830381865afa158015611223573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124791906121e9565b156112df57600b805461125990612128565b80601f016020809104026020016040519081016040528092919081815260200182805461128590612128565b80156112d25780601f106112a7576101008083540402835291602001916112d2565b820191906000526020600020905b8154815290600101906020018083116112b557829003601f168201915b5050505050915050919050565b6009546040516340c7972160e11b8152600481018590526000916001600160a01b03169063818f2e4290602401602060405180830381865afa158015611329573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134d9190612206565b9050816113598561199a565b6113628361199a565b6040516020016113749392919061221f565b60405160208183030381529060405292505050919050565b6008546001600160a01b031633146113b65760405162461bcd60e51b81526004016108ae90612162565b6101f481600c546113c7919061226f565b11156114155760405162461bcd60e51b815260206004820181905260248201527f576f756c6420657863656564206d617820726573657276656420616d6f756e7460448201526064016108ae565b61270f6114256001546000540390565b61142f908361226f565b11156114775760405162461bcd60e51b8152602060048201526017602482015276576f756c6420657863656564206d617820737570706c7960481b60448201526064016108ae565b6114818282611626565b80600c6000828254611493919061226f565b90915550505050565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b6008546001600160a01b031633146114f45760405162461bcd60e51b81526004016108ae90612162565b6001600160a01b0381166115595760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108ae565b610adb816117eb565b6008546001600160a01b0316331461158c5760405162461bcd60e51b81526004016108ae90612162565b6109e4600b8383611b98565b60008054821080156106b4575050600090815260046020526040902054600160e01b161590565b60008160005481101561160d5760008181526004602052604081205490600160e01b8216900361160b575b80600003610f565750600019016000818152600460205260409020546115ea565b505b604051636f96cda160e11b815260040160405180910390fd5b6116408282604051806020016040528060008152506119e9565b5050565b600061164f826115bf565b9050836001600160a01b0316816001600160a01b0316146116825760405162a1148160e81b815260040160405180910390fd5b6000336001600160a01b03861614806116a057506116a0853361149c565b806116bb5750336116b08461074c565b6001600160a01b0316145b9050806116db57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b03841661170257604051633a954ecd60e21b815260040160405180910390fd5b600083815260066020908152604080832080546001600160a01b03191690556001600160a01b038881168452600583528184208054600019019055871683528083208054600101905585835260049091528120600160e11b4260a01b87178117909155831690036117a3576001830160008181526004602052604081205490036117a15760005481146117a15760008181526004602052604090208390555b505b82846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60408051606081018252600080825260208201819052918101919091526000828152600460205260409020546106b490611b5d565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906118a7903390899088908890600401612295565b6020604051808303816000875af19250505080156118e2575060408051601f3d908101601f191682019092526118df918101906122d2565b60015b611940573d808015611910576040519150601f19603f3d011682016040523d82523d6000602084013e611915565b606091505b508051600003611938576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b60408051606081018252600080825260208201819052918101919091526106b4611986836115bf565b611b5d565b6060600a80546106c990612128565b604080516080810191829052607f0190826030600a8206018353600a90045b80156119d757600183039250600a81066030018353600a90046119b9565b50819003601f19909101908152919050565b6000546001600160a01b038416611a1257604051622e076360e81b815260040160405180910390fd5b82600003611a335760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03841660008181526005602090815260408083208054680100000000000000018902019055848352600490915290204260a01b86176001861460e11b1790558190818501903b15611b08575b60405182906001600160a01b038816906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4611ad16000878480600101955087611872565b611aee576040516368d2bf6b60e11b815260040160405180910390fd5b808210611a86578260005414611b0357600080fd5b611b4d565b5b6040516001830192906001600160a01b038816906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4808210611b09575b50600090815561107d9085838684565b604080516060810182526001600160a01b038316815260a083901c67ffffffffffffffff166020820152600160e01b90921615159082015290565b828054611ba490612128565b90600052602060002090601f016020900481019282611bc65760008555611c0c565b82601f10611bdf5782800160ff19823516178555611c0c565b82800160010185558215611c0c579182015b82811115611c0c578235825591602001919060010190611bf1565b50611c18929150611c1c565b5090565b5b80821115611c185760008155600101611c1d565b6001600160e01b031981168114610adb57600080fd5b600060208284031215611c5957600080fd5b8135610f5681611c31565b60005b83811015611c7f578181015183820152602001611c67565b8381111561107d5750506000910152565b60008151808452611ca8816020860160208601611c64565b601f01601f19169290920160200192915050565b602081526000610f566020830184611c90565b600060208284031215611ce157600080fd5b5035919050565b80356001600160a01b0381168114611cff57600080fd5b919050565b60008060408385031215611d1757600080fd5b611d2083611ce8565b946020939093013593505050565b600060208284031215611d4057600080fd5b610f5682611ce8565b600080600060608486031215611d5e57600080fd5b611d6784611ce8565b9250611d7560208501611ce8565b9150604084013590509250925092565b60008060208385031215611d9857600080fd5b823567ffffffffffffffff80821115611db057600080fd5b818501915085601f830112611dc457600080fd5b813581811115611dd357600080fd5b866020828501011115611de557600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611e3657611e36611df7565b604052919050565b60006020808385031215611e5157600080fd5b823567ffffffffffffffff80821115611e6957600080fd5b818501915085601f830112611e7d57600080fd5b813581811115611e8f57611e8f611df7565b8060051b9150611ea0848301611e0d565b8181529183018401918481019088841115611eba57600080fd5b938501935b83851015611ed857843582529385019390850190611ebf565b98975050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015610d7c57611f3c83855180516001600160a01b0316825260208082015167ffffffffffffffff16908301526040908101511515910152565b9284019260609290920191600101611f00565b6020808252825182820181905260009190848201906040850190845b81811015610d7c57835183529284019291840191600101611f6b565b600080600060608486031215611f9c57600080fd5b611fa584611ce8565b95602085013595506040909401359392505050565b8015158114610adb57600080fd5b60008060408385031215611fdb57600080fd5b611fe483611ce8565b91506020830135611ff481611fba565b809150509250929050565b6000806000806080858703121561201557600080fd5b61201e85611ce8565b9350602061202d818701611ce8565b935060408601359250606086013567ffffffffffffffff8082111561205157600080fd5b818801915088601f83011261206557600080fd5b81358181111561207757612077611df7565b612089601f8201601f19168501611e0d565b9150808252898482850101111561209f57600080fd5b808484018584013760008482840101525080935050505092959194509250565b81516001600160a01b0316815260208083015167ffffffffffffffff1690820152604080830151151590820152606081016106b4565b6000806040838503121561210857600080fd5b61211183611ce8565b915061211f60208401611ce8565b90509250929050565b600181811c9082168061213c57607f821691505b60208210810361215c57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600083516121bf818460208801611c64565b8351908301906121d3818360208801611c64565b6102d360f41b9101908152600201949350505050565b6000602082840312156121fb57600080fd5b8151610f5681611fba565b60006020828403121561221857600080fd5b5051919050565b60008451612231818460208901611c64565b845190830190612245818360208901611c64565b602d60f81b91019081528351612262816001840160208801611c64565b0160010195945050505050565b6000821982111561229057634e487b7160e01b600052601160045260246000fd5b500190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906122c890830184611c90565b9695505050505050565b6000602082840312156122e457600080fd5b8151610f5681611c3156fea2646970667358221220057de6761a44e35c9ed6f88351790da909e790b057f33b79dc57d378a6099edc64736f6c634300080e0033

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

00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d5457463552686933336f6172377a6f74334572757354364c6d37713836556a3568547357694539764a4770590000000000000000000000

-----Decoded View---------------
Arg [0] : unrevealedURI (string): ipfs://QmTWF5Rhi33oar7zot3ErusT6Lm7q86Uj5hTsWiE9vJGpY

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000035
Arg [2] : 697066733a2f2f516d5457463552686933336f6172377a6f7433457275735436
Arg [3] : 4c6d37713836556a3568547357694539764a4770590000000000000000000000


Deployed Bytecode Sourcemap

57415:2847:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13157:615;;;;;;;;;;-1:-1:-1;13157:615:0;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;13157:615:0;;;;;;;;18170:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;20238:204::-;;;;;;;;;;-1:-1:-1;20238:204:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1692:32:1;;;1674:51;;1662:2;1647:18;20238:204:0;1528:203:1;19698:474:0;;;;;;;;;;-1:-1:-1;19698:474:0;;;;;:::i;:::-;;:::i;:::-;;59470:382;;;:::i;12211:315::-;;;;;;;;;;-1:-1:-1;12477:12:0;;12264:7;12461:13;:28;12211:315;;;2319:25:1;;;2307:2;2292:18;12211:315:0;2173:177:1;57665:38:0;;;;;;;;;;-1:-1:-1;57665:38:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;21124:170;;;;;;;;;;-1:-1:-1;21124:170:0;;;;;:::i;:::-;;:::i;57634:22::-;;;;;;;;;;-1:-1:-1;57634:22:0;;;;;;;;;;;57768:47;;;;;;;;;;;;57811:4;57768:47;;59176:78;;;;;;;;;;;;;:::i;59262:172::-;;;;;;;;;;;;;:::i;21365:185::-;;;;;;;;;;-1:-1:-1;21365:185:0;;;;;:::i;:::-;;:::i;57607:20::-;;;;;;;;;;-1:-1:-1;57607:20:0;;;;;;;;58738:106;;;;;;;;;;-1:-1:-1;58738:106:0;;;;;:::i;:::-;;:::i;42453:468::-;;;;;;;;;;-1:-1:-1;42453:468:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;17959:144::-;;;;;;;;;;-1:-1:-1;17959:144:0;;;;;:::i;:::-;;:::i;13836:224::-;;;;;;;;;;-1:-1:-1;13836:224:0;;;;;:::i;:::-;;:::i;56377:103::-;;;;;;;;;;;;;:::i;57471:17::-;;;;;;;;;;-1:-1:-1;57471:17:0;;;;-1:-1:-1;;;;;57471:17:0;;;46265:892;;;;;;;;;;-1:-1:-1;46265:892:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;58985:89::-;;;;;;;;;;-1:-1:-1;58985:89:0;;;;;:::i;:::-;;:::i;55726:87::-;;;;;;;;;;-1:-1:-1;55799:6:0;;-1:-1:-1;;;;;55799:6:0;55726:87;;18339:104;;;;;;;;;;;;;:::i;43311:2505::-;;;;;;;;;;-1:-1:-1;43311:2505:0;;;;;:::i;:::-;;:::i;20514:308::-;;;;;;;;;;-1:-1:-1;20514:308:0;;;;;:::i;:::-;;:::i;59082:86::-;;;;;;;;;;;;;:::i;21621:396::-;;;;;;;;;;-1:-1:-1;21621:396:0;;;;;:::i;:::-;;:::i;41874:420::-;;;;;;;;;;-1:-1:-1;41874:420:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;58100:604::-;;;;;;;;;;-1:-1:-1;58100:604:0;;;;;:::i;:::-;;:::i;59929:330::-;;;;;;;;;;-1:-1:-1;59929:330:0;;;;;:::i;:::-;;:::i;20893:164::-;;;;;;;;;;-1:-1:-1;20893:164:0;;;;;:::i;:::-;;:::i;57712:49::-;;;;;;;;;;;;57758:3;57712:49;;56635:201;;;;;;;;;;-1:-1:-1;56635:201:0;;;;;:::i;:::-;;:::i;58852:125::-;;;;;;;;;;-1:-1:-1;58852:125:0;;;;;:::i;:::-;;:::i;13157:615::-;13242:4;-1:-1:-1;;;;;;;;;13542:25:0;;;;:102;;-1:-1:-1;;;;;;;;;;13619:25:0;;;13542:102;:179;;;-1:-1:-1;;;;;;;;;;13696:25:0;;;13542:179;13522:199;13157:615;-1:-1:-1;;13157:615:0:o;18170:100::-;18224:13;18257:5;18250:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18170:100;:::o;20238:204::-;20306:7;20331:16;20339:7;20331;:16::i;:::-;20326:64;;20356:34;;-1:-1:-1;;;20356:34:0;;;;;;;;;;;20326:64;-1:-1:-1;20410:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;20410:24:0;;20238:204::o;19698:474::-;19771:13;19803:27;19822:7;19803:18;:27::i;:::-;19771:61;;19853:5;-1:-1:-1;;;;;19847:11:0;:2;-1:-1:-1;;;;;19847:11:0;;19843:48;;19867:24;;-1:-1:-1;;;19867:24:0;;;;;;;;;;;19843:48;36341:10;-1:-1:-1;;;;;19908:28:0;;;19904:175;;19956:44;19973:5;36341:10;20893:164;:::i;19956:44::-;19951:128;;20028:35;;-1:-1:-1;;;20028:35:0;;;;;;;;;;;19951:128;20091:24;;;;:15;:24;;;;;;:29;;-1:-1:-1;;;;;;20091:29:0;-1:-1:-1;;;;;20091:29:0;;;;;;;;;20136:28;;20091:24;;20136:28;;;;;;;19760:412;19698:474;;:::o;59470:382::-;59522:10;;;;;;;59514:45;;;;-1:-1:-1;;;59514:45:0;;9581:2:1;59514:45:0;;;9563:21:1;9620:2;9600:18;;;9593:30;-1:-1:-1;;;9639:18:1;;;9632:52;9701:18;;59514:45:0;;;;;;;;;59578:10;59592:9;59578:23;59570:54;;;;-1:-1:-1;;;59570:54:0;;9932:2:1;59570:54:0;;;9914:21:1;9971:2;9951:18;;;9944:30;-1:-1:-1;;;9990:18:1;;;9983:48;10048:18;;59570:54:0;9730:342:1;59570:54:0;59651:10;59644:18;;;;:6;:18;;;;;;;;59643:19;59635:57;;;;-1:-1:-1;;;59635:57:0;;10279:2:1;59635:57:0;;;10261:21:1;10318:2;10298:18;;;10291:30;10357:27;10337:18;;;10330:55;10402:18;;59635:57:0;10077:349:1;59635:57:0;57811:4;59711:13;12477:12;;12264:7;12461:13;:28;;12211:315;59711:13;:32;59703:68;;;;-1:-1:-1;;;59703:68:0;;10633:2:1;59703:68:0;;;10615:21:1;10672:2;10652:18;;;10645:30;-1:-1:-1;;;10691:18:1;;;10684:53;10754:18;;59703:68:0;10431:347:1;59703:68:0;59784:24;59794:10;59806:1;59784:9;:24::i;:::-;59826:10;59819:18;;;;:6;:18;;;;;:25;;-1:-1:-1;;59819:25:0;59840:4;59819:25;;;59470:382::o;21124:170::-;21258:28;21268:4;21274:2;21278:7;21258:9;:28::i;:::-;21124:170;;;:::o;59176:78::-;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;59238:8:::1;::::0;;-1:-1:-1;;59226:20:0;::::1;59238:8;::::0;;::::1;59237:9;59226:20;::::0;;59176:78::o;59262:172::-;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;59331:49:::1;::::0;59313:12:::1;::::0;59331:10:::1;::::0;59354:21:::1;::::0;59313:12;59331:49;59313:12;59331:49;59354:21;59331:10;:49:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59312:68;;;59399:7;59391:35;;;::::0;-1:-1:-1;;;59391:35:0;;11556:2:1;59391:35:0::1;::::0;::::1;11538:21:1::0;11595:2;11575:18;;;11568:30;-1:-1:-1;;;11614:18:1;;;11607:45;11669:18;;59391:35:0::1;11354:339:1::0;59391:35:0::1;59301:133;59262:172::o:0;21365:185::-;21503:39;21520:4;21526:2;21530:7;21503:39;;;;;;;;;;;;:16;:39::i;58738:106::-;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;58813:23:::1;:13;58829:7:::0;;58813:23:::1;:::i;42453:468::-:0;42628:15;;42542:23;;42603:22;42628:15;42695:36;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;42695:36:0;;-1:-1:-1;;42695:36:0;;;;;;;;;;;;42658:73;;42751:9;42746:125;42767:14;42762:1;:19;42746:125;;42823:32;42843:8;42852:1;42843:11;;;;;;;;:::i;:::-;;;;;;;42823:19;:32::i;:::-;42807:10;42818:1;42807:13;;;;;;;;:::i;:::-;;;;;;;;;;:48;42783:3;;42746:125;;;-1:-1:-1;42892:10:0;42453:468;-1:-1:-1;;;42453:468:0:o;17959:144::-;18023:7;18066:27;18085:7;18066:18;:27::i;13836:224::-;13900:7;-1:-1:-1;;;;;13924:19:0;;13920:60;;13952:28;;-1:-1:-1;;;13952:28:0;;;;;;;;;;;13920:60;-1:-1:-1;;;;;;13998:25:0;;;;;:18;:25;;;;;;9175:13;13998:54;;13836:224::o;56377:103::-;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;56442:30:::1;56469:1;56442:18;:30::i;:::-;56377:103::o:0;46265:892::-;46335:16;46389:19;46423:25;46463:22;46488:16;46498:5;46488:9;:16::i;:::-;46463:41;;46519:25;46561:14;46547:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46547:29:0;;46519:57;;46591:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;46591:31:0;46642:9;46637:472;46686:14;46671:11;:29;46637:472;;46738:15;46751:1;46738:12;:15::i;:::-;46726:27;;46776:9;:16;;;46817:8;46772:73;46867:14;;-1:-1:-1;;;;;46867:28:0;;46863:111;;46940:14;;;-1:-1:-1;46863:111:0;47017:5;-1:-1:-1;;;;;46996:26:0;:17;-1:-1:-1;;;;;46996:26:0;;46992:102;;47073:1;47047:8;47056:13;;;;;;47047:23;;;;;;;;:::i;:::-;;;;;;:27;;;;;46992:102;46702:3;;46637:472;;;-1:-1:-1;47130:8:0;;46265:892;-1:-1:-1;;;;;;46265:892:0:o;58985:89::-;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;59047:4:::1;:19:::0;;-1:-1:-1;;;;;;59047:19:0::1;-1:-1:-1::0;;;;;59047:19:0;;;::::1;::::0;;;::::1;::::0;;58985:89::o;18339:104::-;18395:13;18428:7;18421:14;;;;;:::i;43311:2505::-;43446:16;43513:4;43504:5;:13;43500:45;;43526:19;;-1:-1:-1;;;43526:19:0;;;;;;;;;;;43500:45;43560:19;43594:17;43614:14;11952:7;11979:13;;11905:95;43614:14;43594:34;-1:-1:-1;43865:9:0;43858:4;:16;43854:73;;;43902:9;43895:16;;43854:73;43941:25;43969:16;43979:5;43969:9;:16::i;:::-;43941:44;;44163:4;44155:5;:12;44151:278;;;44210:12;;;44245:31;;;44241:111;;;44321:11;44301:31;;44241:111;44169:198;44151:278;;;-1:-1:-1;44412:1:0;44151:278;44443:25;44485:17;44471:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44471:32:0;;44443:60;;44522:17;44543:1;44522:22;44518:78;;44572:8;-1:-1:-1;44565:15:0;;-1:-1:-1;;;44565:15:0;44518:78;44740:31;44774:26;44794:5;44774:19;:26::i;:::-;44740:60;;44815:25;45060:9;:16;;;45055:92;;-1:-1:-1;45117:14:0;;45055:92;45178:5;45161:478;45190:4;45185:1;:9;;:45;;;;;45213:17;45198:11;:32;;45185:45;45161:478;;;45268:15;45281:1;45268:12;:15::i;:::-;45256:27;;45306:9;:16;;;45347:8;45302:73;45397:14;;-1:-1:-1;;;;;45397:28:0;;45393:111;;45470:14;;;-1:-1:-1;45393:111:0;45547:5;-1:-1:-1;;;;;45526:26:0;:17;-1:-1:-1;;;;;45526:26:0;;45522:102;;45603:1;45577:8;45586:13;;;;;;45577:23;;;;;;;;:::i;:::-;;;;;;:27;;;;;45522:102;45232:3;;45161:478;;;-1:-1:-1;;;45724:29:0;;;-1:-1:-1;45731:8:0;;-1:-1:-1;;43311:2505:0;;;;;;:::o;20514:308::-;36341:10;-1:-1:-1;;;;;20613:31:0;;;20609:61;;20653:17;;-1:-1:-1;;;20653:17:0;;;;;;;;;;;20609:61;36341:10;20683:39;;;;:18;:39;;;;;;;;-1:-1:-1;;;;;20683:49:0;;;;;;;;;;;;:60;;-1:-1:-1;;20683:60:0;;;;;;;;;;20759:55;;540:41:1;;;20683:49:0;;36341:10;20759:55;;513:18:1;20759:55:0;;;;;;;20514:308;;:::o;59082:86::-;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;59150:10:::1;::::0;;-1:-1:-1;;59136:24:0;::::1;59150:10;::::0;;;::::1;;;59149:11;59136:24:::0;;::::1;;::::0;;59082:86::o;21621:396::-;21788:28;21798:4;21804:2;21808:7;21788:9;:28::i;:::-;-1:-1:-1;;;;;21831:14:0;;;:19;21827:183;;21870:56;21901:4;21907:2;21911:7;21920:5;21870:30;:56::i;:::-;21865:145;;21954:40;;-1:-1:-1;;;21954:40:0;;;;;;;;;;;21865:145;21621:396;;;;:::o;41874:420::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11952:7:0;11979:13;42059:7;:25;42026:103;;42108:9;41874:420;-1:-1:-1;;41874:420:0:o;42026:103::-;42151:21;42164:7;42151:12;:21::i;:::-;42139:33;;42187:9;:16;;;42183:65;;;42227:9;41874:420;-1:-1:-1;;41874:420:0:o;42183:65::-;42265:21;42278:7;42265:12;:21::i;58100:604::-;58223:8;;58192:13;;58223:8;;58218:63;;58255:14;58248:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58100:604;;;:::o;58218:63::-;58293:21;58317:10;:8;:10::i;:::-;58350:4;;58293:34;;-1:-1:-1;;;;;;58350:4:0;58338:126;;58417:7;58426:18;58436:7;58426:9;:18::i;:::-;58400:51;;;;;;;;;:::i;:::-;;;;;;;;;;;;;58386:66;;;58100:604;;;:::o;58338:126::-;58480:4;;:20;;-1:-1:-1;;;58480:20:0;;;;;2319:25:1;;;-1:-1:-1;;;;;58480:4:0;;;;:11;;2292:18:1;;58480:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58476:74;;;58524:14;58517:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58100:604;;;:::o;58476:74::-;58578:4;;:24;;-1:-1:-1;;;58578:24:0;;;;;2319:25:1;;;58562:13:0;;-1:-1:-1;;;;;58578:4:0;;:15;;2292:18:1;;58578:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58562:40;;58644:7;58653:18;58663:7;58653:9;:18::i;:::-;58678:16;58688:5;58678:9;:16::i;:::-;58627:68;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;58613:83;;;;58100:604;;;:::o;59929:330::-;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;57758:3:::1;60024:6;60012:9;;:18;;;;:::i;:::-;:41;;60004:86;;;::::0;-1:-1:-1;;;60004:86:0;;14153:2:1;60004:86:0::1;::::0;::::1;14135:21:1::0;;;14172:18;;;14165:30;14231:34;14211:18;;;14204:62;14283:18;;60004:86:0::1;13951:356:1::0;60004:86:0::1;57811:4;60118:13;12477:12:::0;;12264:7;12461:13;:28;;12211:315;60118:13:::1;60109:22;::::0;:6;:22:::1;:::i;:::-;:42;;60101:78;;;::::0;-1:-1:-1;;;60101:78:0;;10633:2:1;60101:78:0::1;::::0;::::1;10615:21:1::0;10672:2;10652:18;;;10645:30;-1:-1:-1;;;10691:18:1;;;10684:53;10754:18;;60101:78:0::1;10431:347:1::0;60101:78:0::1;60200:21;60210:2;60214:6;60200:9;:21::i;:::-;60245:6;60232:9;;:19;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;;59929:330:0:o;20893:164::-;-1:-1:-1;;;;;21014:25:0;;;20990:4;21014:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;20893:164::o;56635:201::-;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;56724:22:0;::::1;56716:73;;;::::0;-1:-1:-1;;;56716:73:0;;14514:2:1;56716:73:0::1;::::0;::::1;14496:21:1::0;14553:2;14533:18;;;14526:30;14592:34;14572:18;;;14565:62;-1:-1:-1;;;14643:18:1;;;14636:36;14689:19;;56716:73:0::1;14312:402:1::0;56716:73:0::1;56800:28;56819:8;56800:18;:28::i;58852:125::-:0;55799:6;;-1:-1:-1;;;;;55799:6:0;36341:10;55946:23;55938:68;;;;-1:-1:-1;;;55938:68:0;;;;;;;:::i;:::-;58939:30:::1;:14;58956:13:::0;;58939:30:::1;:::i;22272:273::-:0;22329:4;22419:13;;22409:7;:23;22366:152;;;;-1:-1:-1;;22470:26:0;;;;:17;:26;;;;;;-1:-1:-1;;;22470:43:0;:48;;22272:273::o;15474:1129::-;15541:7;15576;15678:13;;15671:4;:20;15667:869;;;15716:14;15733:23;;;:17;:23;;;;;;;-1:-1:-1;;;15822:23:0;;:28;;15818:699;;16341:113;16348:6;16358:1;16348:11;16341:113;;-1:-1:-1;;;16419:6:0;16401:25;;;;:17;:25;;;;;;16341:113;;15818:699;15693:843;15667:869;16564:31;;-1:-1:-1;;;16564:31:0;;;;;;;;;;;22629:104;22698:27;22708:2;22712:8;22698:27;;;;;;;;;;;;:9;:27::i;:::-;22629:104;;:::o;27511:2515::-;27626:27;27656;27675:7;27656:18;:27::i;:::-;27626:57;;27741:4;-1:-1:-1;;;;;27700:45:0;27716:19;-1:-1:-1;;;;;27700:45:0;;27696:86;;27754:28;;-1:-1:-1;;;27754:28:0;;;;;;;;;;;27696:86;27795:22;36341:10;-1:-1:-1;;;;;27821:27:0;;;;:87;;-1:-1:-1;27865:43:0;27882:4;36341:10;20893:164;:::i;27865:43::-;27821:147;;;-1:-1:-1;36341:10:0;27925:20;27937:7;27925:11;:20::i;:::-;-1:-1:-1;;;;;27925:43:0;;27821:147;27795:174;;27987:17;27982:66;;28013:35;;-1:-1:-1;;;28013:35:0;;;;;;;;;;;27982:66;-1:-1:-1;;;;;28063:16:0;;28059:52;;28088:23;;-1:-1:-1;;;28088:23:0;;;;;;;;;;;28059:52;28240:24;;;;:15;:24;;;;;;;;28233:31;;-1:-1:-1;;;;;;28233:31:0;;;-1:-1:-1;;;;;28632:24:0;;;;;:18;:24;;;;;28630:26;;-1:-1:-1;;28630:26:0;;;28701:22;;;;;;;28699:24;;-1:-1:-1;28699:24:0;;;28994:26;;;:17;:26;;;;;-1:-1:-1;;;29082:15:0;9829:3;29082:41;29040:84;;:128;;28994:174;;;29288:46;;:51;;29284:626;;29392:1;29382:11;;29360:19;29515:30;;;:17;:30;;;;;;:35;;29511:384;;29653:13;;29638:11;:28;29634:242;;29800:30;;;;:17;:30;;;;;:52;;;29634:242;29341:569;29284:626;29957:7;29953:2;-1:-1:-1;;;;;29938:27:0;29947:4;-1:-1:-1;;;;;29938:27:0;;;;;;;;;;;27615:2411;;27511:2515;;;:::o;56996:191::-;57089:6;;;-1:-1:-1;;;;;57106:17:0;;;-1:-1:-1;;;;;;57106:17:0;;;;;;;57139:40;;57089:6;;;57106:17;57089:6;;57139:40;;57070:16;;57139:40;57059:128;56996:191;:::o;17083:153::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;17203:24:0;;;;:17;:24;;;;;;17184:44;;:18;:44::i;33723:716::-;33907:88;;-1:-1:-1;;;33907:88:0;;33886:4;;-1:-1:-1;;;;;33907:45:0;;;;;:88;;36341:10;;33974:4;;33980:7;;33989:5;;33907:88;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33907:88:0;;;;;;;;-1:-1:-1;;33907:88:0;;;;;;;;;;;;:::i;:::-;;;33903:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34190:6;:13;34207:1;34190:18;34186:235;;34236:40;;-1:-1:-1;;;34236:40:0;;;;;;;;;;;34186:235;34379:6;34373:13;34364:6;34360:2;34356:15;34349:38;33903:529;-1:-1:-1;;;;;;34066:64:0;-1:-1:-1;;;34066:64:0;;-1:-1:-1;33723:716:0;;;;;;:::o;17739:158::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;17842:47:0;17861:27;17880:7;17861:18;:27::i;:::-;17842:18;:47::i;57978:114::-;58038:13;58071;58064:20;;;;;:::i;36465:1959::-;36936:4;36930:11;;36943:3;36926:21;;37021:17;;;;37718:11;;;37597:5;37850:2;37864;37854:13;;37846:22;37718:11;37833:36;37905:2;37895:13;;37488:682;37924:4;37488:682;;;38099:1;38094:3;38090:11;38083:18;;38150:2;38144:4;38140:13;38136:2;38132:22;38127:3;38119:36;38020:2;38010:13;;37488:682;;;-1:-1:-1;38212:13:0;;;-1:-1:-1;;38327:12:0;;;38387:19;;;38327:12;36465:1959;-1:-1:-1;36465:1959:0:o;23106:2236::-;23229:20;23252:13;-1:-1:-1;;;;;23280:16:0;;23276:48;;23305:19;;-1:-1:-1;;;23305:19:0;;;;;;;;;;;23276:48;23339:8;23351:1;23339:13;23335:44;;23361:18;;-1:-1:-1;;;23361:18:0;;;;;;;;;;;23335:44;-1:-1:-1;;;;;23928:22:0;;;;;;:18;:22;;;;9312:2;23928:22;;;:70;;23966:31;23954:44;;23928:70;;;24241:31;;;:17;:31;;;;;24334:15;9829:3;24334:41;24292:84;;-1:-1:-1;24412:13:0;;10092:3;24397:56;24292:162;24241:213;;:31;;24535:23;;;;24579:14;:19;24575:635;;24619:313;24650:38;;24675:12;;-1:-1:-1;;;;;24650:38:0;;;24667:1;;24650:38;;24667:1;;24650:38;24716:69;24755:1;24759:2;24763:14;;;;;;24779:5;24716:30;:69::i;:::-;24711:174;;24821:40;;-1:-1:-1;;;24821:40:0;;;;;;;;;;;24711:174;24927:3;24912:12;:18;24619:313;;25013:12;24996:13;;:29;24992:43;;25027:8;;;24992:43;24575:635;;;25076:119;25107:40;;25132:14;;;;;-1:-1:-1;;;;;25107:40:0;;;25124:1;;25107:40;;25124:1;;25107:40;25190:3;25175:12;:18;25076:119;;24575:635;-1:-1:-1;25224:13:0;:28;;;25274:60;;25307:2;25311:12;25325:8;25274:60;:::i;16697:295::-;-1:-1:-1;;;;;;;;;;;;;16807:41:0;;;;9829:3;16893:32;;;16859:67;;-1:-1:-1;;;16859:67:0;-1:-1:-1;;;16956:23:0;;;:28;;-1:-1:-1;;;16937:47:0;-1:-1:-1;16697:295:0:o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:131:1;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;592:258::-;664:1;674:113;688:6;685:1;682:13;674:113;;;764:11;;;758:18;745:11;;;738:39;710:2;703:10;674:113;;;805:6;802:1;799:13;796:48;;;-1:-1:-1;;840:1:1;822:16;;815:27;592:258::o;855:::-;897:3;935:5;929:12;962:6;957:3;950:19;978:63;1034:6;1027:4;1022:3;1018:14;1011:4;1004:5;1000:16;978:63;:::i;:::-;1095:2;1074:15;-1:-1:-1;;1070:29:1;1061:39;;;;1102:4;1057:50;;855:258;-1:-1:-1;;855:258:1:o;1118:220::-;1267:2;1256:9;1249:21;1230:4;1287:45;1328:2;1317:9;1313:18;1305:6;1287:45;:::i;1343:180::-;1402:6;1455:2;1443:9;1434:7;1430:23;1426:32;1423:52;;;1471:1;1468;1461:12;1423:52;-1:-1:-1;1494:23:1;;1343:180;-1:-1:-1;1343:180:1:o;1736:173::-;1804:20;;-1:-1:-1;;;;;1853:31:1;;1843:42;;1833:70;;1899:1;1896;1889:12;1833:70;1736:173;;;:::o;1914:254::-;1982:6;1990;2043:2;2031:9;2022:7;2018:23;2014:32;2011:52;;;2059:1;2056;2049:12;2011:52;2082:29;2101:9;2082:29;:::i;:::-;2072:39;2158:2;2143:18;;;;2130:32;;-1:-1:-1;;;1914:254:1:o;2355:186::-;2414:6;2467:2;2455:9;2446:7;2442:23;2438:32;2435:52;;;2483:1;2480;2473:12;2435:52;2506:29;2525:9;2506:29;:::i;2546:328::-;2623:6;2631;2639;2692:2;2680:9;2671:7;2667:23;2663:32;2660:52;;;2708:1;2705;2698:12;2660:52;2731:29;2750:9;2731:29;:::i;:::-;2721:39;;2779:38;2813:2;2802:9;2798:18;2779:38;:::i;:::-;2769:48;;2864:2;2853:9;2849:18;2836:32;2826:42;;2546:328;;;;;:::o;2879:592::-;2950:6;2958;3011:2;2999:9;2990:7;2986:23;2982:32;2979:52;;;3027:1;3024;3017:12;2979:52;3067:9;3054:23;3096:18;3137:2;3129:6;3126:14;3123:34;;;3153:1;3150;3143:12;3123:34;3191:6;3180:9;3176:22;3166:32;;3236:7;3229:4;3225:2;3221:13;3217:27;3207:55;;3258:1;3255;3248:12;3207:55;3298:2;3285:16;3324:2;3316:6;3313:14;3310:34;;;3340:1;3337;3330:12;3310:34;3385:7;3380:2;3371:6;3367:2;3363:15;3359:24;3356:37;3353:57;;;3406:1;3403;3396:12;3353:57;3437:2;3429:11;;;;;3459:6;;-1:-1:-1;2879:592:1;;-1:-1:-1;;;;2879:592:1:o;3476:127::-;3537:10;3532:3;3528:20;3525:1;3518:31;3568:4;3565:1;3558:15;3592:4;3589:1;3582:15;3608:275;3679:2;3673:9;3744:2;3725:13;;-1:-1:-1;;3721:27:1;3709:40;;3779:18;3764:34;;3800:22;;;3761:62;3758:88;;;3826:18;;:::i;:::-;3862:2;3855:22;3608:275;;-1:-1:-1;3608:275:1:o;3888:946::-;3972:6;4003:2;4046;4034:9;4025:7;4021:23;4017:32;4014:52;;;4062:1;4059;4052:12;4014:52;4102:9;4089:23;4131:18;4172:2;4164:6;4161:14;4158:34;;;4188:1;4185;4178:12;4158:34;4226:6;4215:9;4211:22;4201:32;;4271:7;4264:4;4260:2;4256:13;4252:27;4242:55;;4293:1;4290;4283:12;4242:55;4329:2;4316:16;4351:2;4347;4344:10;4341:36;;;4357:18;;:::i;:::-;4403:2;4400:1;4396:10;4386:20;;4426:28;4450:2;4446;4442:11;4426:28;:::i;:::-;4488:15;;;4558:11;;;4554:20;;;4519:12;;;;4586:19;;;4583:39;;;4618:1;4615;4608:12;4583:39;4642:11;;;;4662:142;4678:6;4673:3;4670:15;4662:142;;;4744:17;;4732:30;;4695:12;;;;4782;;;;4662:142;;;4823:5;3888:946;-1:-1:-1;;;;;;;;3888:946:1:o;5122:720::-;5353:2;5405:21;;;5475:13;;5378:18;;;5497:22;;;5324:4;;5353:2;5576:15;;;;5550:2;5535:18;;;5324:4;5619:197;5633:6;5630:1;5627:13;5619:197;;;5682:52;5730:3;5721:6;5715:13;4923:12;;-1:-1:-1;;;;;4919:38:1;4907:51;;5011:4;5000:16;;;4994:23;5019:18;4990:48;4974:14;;;4967:72;5102:4;5091:16;;;5085:23;5078:31;5071:39;5055:14;;5048:63;4839:278;5682:52;5791:15;;;;5763:4;5754:14;;;;;5655:1;5648:9;5619:197;;6069:632;6240:2;6292:21;;;6362:13;;6265:18;;;6384:22;;;6211:4;;6240:2;6463:15;;;;6437:2;6422:18;;;6211:4;6506:169;6520:6;6517:1;6514:13;6506:169;;;6581:13;;6569:26;;6650:15;;;;6615:12;;;;6542:1;6535:9;6506:169;;6706:322;6783:6;6791;6799;6852:2;6840:9;6831:7;6827:23;6823:32;6820:52;;;6868:1;6865;6858:12;6820:52;6891:29;6910:9;6891:29;:::i;:::-;6881:39;6967:2;6952:18;;6939:32;;-1:-1:-1;7018:2:1;7003:18;;;6990:32;;6706:322;-1:-1:-1;;;6706:322:1:o;7033:118::-;7119:5;7112:13;7105:21;7098:5;7095:32;7085:60;;7141:1;7138;7131:12;7156:315;7221:6;7229;7282:2;7270:9;7261:7;7257:23;7253:32;7250:52;;;7298:1;7295;7288:12;7250:52;7321:29;7340:9;7321:29;:::i;:::-;7311:39;;7400:2;7389:9;7385:18;7372:32;7413:28;7435:5;7413:28;:::i;:::-;7460:5;7450:15;;;7156:315;;;;;:::o;7476:980::-;7571:6;7579;7587;7595;7648:3;7636:9;7627:7;7623:23;7619:33;7616:53;;;7665:1;7662;7655:12;7616:53;7688:29;7707:9;7688:29;:::i;:::-;7678:39;;7736:2;7757:38;7791:2;7780:9;7776:18;7757:38;:::i;:::-;7747:48;;7842:2;7831:9;7827:18;7814:32;7804:42;;7897:2;7886:9;7882:18;7869:32;7920:18;7961:2;7953:6;7950:14;7947:34;;;7977:1;7974;7967:12;7947:34;8015:6;8004:9;8000:22;7990:32;;8060:7;8053:4;8049:2;8045:13;8041:27;8031:55;;8082:1;8079;8072:12;8031:55;8118:2;8105:16;8140:2;8136;8133:10;8130:36;;;8146:18;;:::i;:::-;8188:53;8231:2;8212:13;;-1:-1:-1;;8208:27:1;8204:36;;8188:53;:::i;:::-;8175:66;;8264:2;8257:5;8250:17;8304:7;8299:2;8294;8290;8286:11;8282:20;8279:33;8276:53;;;8325:1;8322;8315:12;8276:53;8380:2;8375;8371;8367:11;8362:2;8355:5;8351:14;8338:45;8424:1;8419:2;8414;8407:5;8403:14;8399:23;8392:34;;8445:5;8435:15;;;;;7476:980;;;;;;;:::o;8461:263::-;4923:12;;-1:-1:-1;;;;;4919:38:1;4907:51;;5011:4;5000:16;;;4994:23;5019:18;4990:48;4974:14;;;4967:72;5102:4;5091:16;;;5085:23;5078:31;5071:39;5055:14;;;5048:63;8655:2;8640:18;;8667:51;4839:278;8729:260;8797:6;8805;8858:2;8846:9;8837:7;8833:23;8829:32;8826:52;;;8874:1;8871;8864:12;8826:52;8897:29;8916:9;8897:29;:::i;:::-;8887:39;;8945:38;8979:2;8968:9;8964:18;8945:38;:::i;:::-;8935:48;;8729:260;;;;;:::o;8994:380::-;9073:1;9069:12;;;;9116;;;9137:61;;9191:4;9183:6;9179:17;9169:27;;9137:61;9244:2;9236:6;9233:14;9213:18;9210:38;9207:161;;9290:10;9285:3;9281:20;9278:1;9271:31;9325:4;9322:1;9315:15;9353:4;9350:1;9343:15;9207:161;;8994:380;;;:::o;10783:356::-;10985:2;10967:21;;;11004:18;;;10997:30;11063:34;11058:2;11043:18;;11036:62;11130:2;11115:18;;10783:356::o;11698:127::-;11759:10;11754:3;11750:20;11747:1;11740:31;11790:4;11787:1;11780:15;11814:4;11811:1;11804:15;11830:634;12110:3;12148:6;12142:13;12164:53;12210:6;12205:3;12198:4;12190:6;12186:17;12164:53;:::i;:::-;12280:13;;12239:16;;;;12302:57;12280:13;12239:16;12336:4;12324:17;;12302:57;:::i;:::-;-1:-1:-1;;;12381:20:1;;12410:19;;;12456:1;12445:13;;11830:634;-1:-1:-1;;;;11830:634:1:o;12469:245::-;12536:6;12589:2;12577:9;12568:7;12564:23;12560:32;12557:52;;;12605:1;12602;12595:12;12557:52;12637:9;12631:16;12656:28;12678:5;12656:28;:::i;12719:184::-;12789:6;12842:2;12830:9;12821:7;12817:23;12813:32;12810:52;;;12858:1;12855;12848:12;12810:52;-1:-1:-1;12881:16:1;;12719:184;-1:-1:-1;12719:184:1:o;12908:808::-;13236:3;13274:6;13268:13;13290:53;13336:6;13331:3;13324:4;13316:6;13312:17;13290:53;:::i;:::-;13406:13;;13365:16;;;;13428:57;13406:13;13365:16;13462:4;13450:17;;13428:57;:::i;:::-;-1:-1:-1;;;13507:20:1;;13536:18;;;13579:13;;13601:65;13579:13;13653:1;13642:13;;13635:4;13623:17;;13601:65;:::i;:::-;13686:20;13708:1;13682:28;;12908:808;-1:-1:-1;;;;;12908:808:1:o;13721:225::-;13761:3;13792:1;13788:6;13785:1;13782:13;13779:136;;;13837:10;13832:3;13828:20;13825:1;13818:31;13872:4;13869:1;13862:15;13900:4;13897:1;13890:15;13779:136;-1:-1:-1;13931:9:1;;13721:225::o;14719:489::-;-1:-1:-1;;;;;14988:15:1;;;14970:34;;15040:15;;15035:2;15020:18;;15013:43;15087:2;15072:18;;15065:34;;;15135:3;15130:2;15115:18;;15108:31;;;14913:4;;15156:46;;15182:19;;15174:6;15156:46;:::i;:::-;15148:54;14719:489;-1:-1:-1;;;;;;14719:489:1:o;15213:249::-;15282:6;15335:2;15323:9;15314:7;15310:23;15306:32;15303:52;;;15351:1;15348;15341:12;15303:52;15383:9;15377:16;15402:30;15426:5;15402:30;:::i

Swarm Source

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