ETH Price: $2,412.77 (-1.09%)

Transaction Decoder

Block:
16169951 at Dec-12-2022 04:55:59 PM +UTC
Transaction Fee:
0.002161688363345898 ETH $5.22
Gas Used:
101,622 Gas / 21.271854159 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x1aa0F853...80B7d5848
0x9A808940...7Ba2C71dB
0.341453751744269199 Eth
Nonce: 66
0.339292073380923301 Eth
Nonce: 67
0.002161678363345898
7.209400611550693179 Eth7.209553044550693179 Eth0.000152433
0xd60E9443...5133AD3eD 0.04999439 Eth0.04999438 Eth0.00000001

Execution Trace

Harvestooor.sellTokens( tokens= )
  • TheKindnessProject.supportsInterface( interfaceId=System.Byte[] ) => ( True )
  • TheKindnessProject.supportsInterface( interfaceId=System.Byte[] ) => ( False )
  • TheKindnessProject.supportsInterface( interfaceId=System.Byte[] ) => ( True )
  • TheKindnessProject.ownerOf( tokenId=323 ) => ( 0x9A808940F61BffF0f61b434CCcE31657Ba2C71dB )
  • TheKindnessProject.safeTransferFrom( from=0x9A808940F61BffF0f61b434CCcE31657Ba2C71dB, to=0xd60E94434310381575C5e67Bb1D3E125133AD3eD, tokenId=323 )
    • Harvestooor.onERC721Received( 0xd60E94434310381575C5e67Bb1D3E125133AD3eD, from=0x9A808940F61BffF0f61b434CCcE31657Ba2C71dB, tokenId=323, 0x )
    • ETH 0.00000001 0x9a808940f61bfff0f61b434ccce31657ba2c71db.CALL( )
      File 1 of 2: Harvestooor
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor() {
              _transferOwnership(_msgSender());
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              _checkOwner();
              _;
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if the sender is not the owner.
           */
          function _checkOwner() internal view virtual {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions anymore. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby removing any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              _transferOwnership(address(0));
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              _transferOwnership(newOwner);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual {
              address oldOwner = _owner;
              _owner = newOwner;
              emit OwnershipTransferred(oldOwner, newOwner);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which allows children to implement an emergency stop
       * mechanism that can be triggered by an authorized account.
       *
       * This module is used through inheritance. It will make available the
       * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
       * the functions of your contract. Note that they will not be pausable by
       * simply including this module, only once the modifiers are put in place.
       */
      abstract contract Pausable is Context {
          /**
           * @dev Emitted when the pause is triggered by `account`.
           */
          event Paused(address account);
          /**
           * @dev Emitted when the pause is lifted by `account`.
           */
          event Unpaused(address account);
          bool private _paused;
          /**
           * @dev Initializes the contract in unpaused state.
           */
          constructor() {
              _paused = false;
          }
          /**
           * @dev Modifier to make a function callable only when the contract is not paused.
           *
           * Requirements:
           *
           * - The contract must not be paused.
           */
          modifier whenNotPaused() {
              _requireNotPaused();
              _;
          }
          /**
           * @dev Modifier to make a function callable only when the contract is paused.
           *
           * Requirements:
           *
           * - The contract must be paused.
           */
          modifier whenPaused() {
              _requirePaused();
              _;
          }
          /**
           * @dev Returns true if the contract is paused, and false otherwise.
           */
          function paused() public view virtual returns (bool) {
              return _paused;
          }
          /**
           * @dev Throws if the contract is paused.
           */
          function _requireNotPaused() internal view virtual {
              require(!paused(), "Pausable: paused");
          }
          /**
           * @dev Throws if the contract is not paused.
           */
          function _requirePaused() internal view virtual {
              require(paused(), "Pausable: not paused");
          }
          /**
           * @dev Triggers stopped state.
           *
           * Requirements:
           *
           * - The contract must not be paused.
           */
          function _pause() internal virtual whenNotPaused {
              _paused = true;
              emit Paused(_msgSender());
          }
          /**
           * @dev Returns to normal state.
           *
           * Requirements:
           *
           * - The contract must be paused.
           */
          function _unpause() internal virtual whenPaused {
              _paused = false;
              emit Unpaused(_msgSender());
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Contract module that helps prevent reentrant calls to a function.
       *
       * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
       * available, which can be applied to functions to make sure there are no nested
       * (reentrant) calls to them.
       *
       * Note that because there is a single `nonReentrant` guard, functions marked as
       * `nonReentrant` may not call one another. This can be worked around by making
       * those functions `private`, and then adding `external` `nonReentrant` entry
       * points to them.
       *
       * TIP: If you would like to learn more about reentrancy and alternative ways
       * to protect against it, check out our blog post
       * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
       */
      abstract contract ReentrancyGuard {
          // Booleans are more expensive than uint256 or any type that takes up a full
          // word because each write operation emits an extra SLOAD to first read the
          // slot's contents, replace the bits taken up by the boolean, and then write
          // back. This is the compiler's defense against contract upgrades and
          // pointer aliasing, and it cannot be disabled.
          // The values being non-zero value makes deployment a bit more expensive,
          // but in exchange the refund on every call to nonReentrant will be lower in
          // amount. Since refunds are capped to a percentage of the total
          // transaction's gas, it is best to keep them low in cases like this one, to
          // increase the likelihood of the full refund coming into effect.
          uint256 private constant _NOT_ENTERED = 1;
          uint256 private constant _ENTERED = 2;
          uint256 private _status;
          constructor() {
              _status = _NOT_ENTERED;
          }
          /**
           * @dev Prevents a contract from calling itself, directly or indirectly.
           * Calling a `nonReentrant` function from another `nonReentrant`
           * function is not supported. It is possible to prevent this from happening
           * by making the `nonReentrant` function external, and making it call a
           * `private` function that does the actual work.
           */
          modifier nonReentrant() {
              // On the first call to nonReentrant, _notEntered will be true
              require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
              // Any calls to nonReentrant after this point will fail
              _status = _ENTERED;
              _;
              // By storing the original value once again, a refund is triggered (see
              // https://eips.ethereum.org/EIPS/eip-2200)
              _status = _NOT_ENTERED;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
      pragma solidity ^0.8.0;
      import "../../utils/introspection/IERC165.sol";
      /**
       * @dev Required interface of an ERC721 compliant contract.
       */
      interface IERC721 is IERC165 {
          /**
           * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
           */
          event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
          /**
           * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
           */
          event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
          /**
           * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
           */
          event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
          /**
           * @dev Returns the number of tokens in ``owner``'s account.
           */
          function balanceOf(address owner) external view returns (uint256 balance);
          /**
           * @dev Returns the owner of the `tokenId` token.
           *
           * Requirements:
           *
           * - `tokenId` must exist.
           */
          function ownerOf(uint256 tokenId) external view returns (address owner);
          /**
           * @dev Safely transfers `tokenId` token from `from` to `to`.
           *
           * Requirements:
           *
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           * - `tokenId` token must exist and be owned by `from`.
           * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
           * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
           *
           * Emits a {Transfer} event.
           */
          function safeTransferFrom(
              address from,
              address to,
              uint256 tokenId,
              bytes calldata data
          ) external;
          /**
           * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
           * are aware of the ERC721 protocol to prevent tokens from being forever locked.
           *
           * Requirements:
           *
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           * - `tokenId` token must exist and be owned by `from`.
           * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
           * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
           *
           * Emits a {Transfer} event.
           */
          function safeTransferFrom(
              address from,
              address to,
              uint256 tokenId
          ) external;
          /**
           * @dev Transfers `tokenId` token from `from` to `to`.
           *
           * WARNING: 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);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
      pragma solidity ^0.8.0;
      /**
       * @title ERC721 token receiver interface
       * @dev Interface for any contract that wants to support safeTransfers
       * from ERC721 asset contracts.
       */
      interface IERC721Receiver {
          /**
           * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
           * by `operator` from `from`, this function is called.
           *
           * It must return its Solidity selector to confirm the token transfer.
           * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
           *
           * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
           */
          function onERC721Received(
              address operator,
              address from,
              uint256 tokenId,
              bytes calldata data
          ) external returns (bytes4);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
      pragma solidity ^0.8.1;
      /**
       * @dev Collection of functions related to the address type
       */
      library Address {
          /**
           * @dev Returns true if `account` is a contract.
           *
           * [IMPORTANT]
           * ====
           * It is unsafe to assume that an address for which this function returns
           * false is an externally-owned account (EOA) and not a contract.
           *
           * Among others, `isContract` will return false for the following
           * types of addresses:
           *
           *  - an externally-owned account
           *  - a contract in construction
           *  - an address where a contract will be created
           *  - an address where a contract lived, but was destroyed
           * ====
           *
           * [IMPORTANT]
           * ====
           * You shouldn't rely on `isContract` to protect against flash loan attacks!
           *
           * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
           * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
           * constructor.
           * ====
           */
          function isContract(address account) internal view returns (bool) {
              // This method relies on extcodesize/address.code.length, which returns 0
              // for contracts in construction, since the code is only stored at the end
              // of the constructor execution.
              return account.code.length > 0;
          }
          /**
           * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
           * `recipient`, forwarding all available gas and reverting on errors.
           *
           * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
           * of certain opcodes, possibly making contracts go over the 2300 gas limit
           * imposed by `transfer`, making them unable to receive funds via
           * `transfer`. {sendValue} removes this limitation.
           *
           * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
           *
           * IMPORTANT: because control is transferred to `recipient`, care must be
           * taken to not create reentrancy vulnerabilities. Consider using
           * {ReentrancyGuard} or the
           * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
           */
          function sendValue(address payable recipient, uint256 amount) internal {
              require(address(this).balance >= amount, "Address: insufficient balance");
              (bool success, ) = recipient.call{value: amount}("");
              require(success, "Address: unable to send value, recipient may have reverted");
          }
          /**
           * @dev Performs a Solidity function call using a low level `call`. A
           * plain `call` is an unsafe replacement for a function call: use this
           * function instead.
           *
           * If `target` reverts with a revert reason, it is bubbled up by this
           * function (like regular Solidity function calls).
           *
           * Returns the raw returned data. To convert to the expected return value,
           * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
           *
           * Requirements:
           *
           * - `target` must be a contract.
           * - calling `target` with `data` must not revert.
           *
           * _Available since v3.1._
           */
          function functionCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionCall(target, data, "Address: low-level call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
           * `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, 0, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but also transferring `value` wei to `target`.
           *
           * Requirements:
           *
           * - the calling contract must have an ETH balance of at least `value`.
           * - the called Solidity function must be `payable`.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
          }
          /**
           * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
           * with `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(address(this).balance >= value, "Address: insufficient balance for call");
              require(isContract(target), "Address: call to non-contract");
              (bool success, bytes memory returndata) = target.call{value: value}(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
              return functionStaticCall(target, data, "Address: low-level static call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal view returns (bytes memory) {
              require(isContract(target), "Address: static call to non-contract");
              (bool success, bytes memory returndata) = target.staticcall(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionDelegateCall(target, data, "Address: low-level delegate call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(isContract(target), "Address: delegate call to non-contract");
              (bool success, bytes memory returndata) = target.delegatecall(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
           * revert reason using the provided one.
           *
           * _Available since v4.3._
           */
          function verifyCallResult(
              bool success,
              bytes memory returndata,
              string memory errorMessage
          ) internal pure returns (bytes memory) {
              if (success) {
                  return returndata;
              } else {
                  // Look for revert reason and bubble it up if present
                  if (returndata.length > 0) {
                      // The easiest way to bubble the revert reason is using memory via assembly
                      /// @solidity memory-safe-assembly
                      assembly {
                          let returndata_size := mload(returndata)
                          revert(add(32, returndata), returndata_size)
                      }
                  } else {
                      revert(errorMessage);
                  }
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // 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;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.7.2) (utils/introspection/ERC165Checker.sol)
      pragma solidity ^0.8.0;
      import "./IERC165.sol";
      /**
       * @dev Library used to query support of an interface declared via {IERC165}.
       *
       * Note that these functions return the actual result of the query: they do not
       * `revert` if an interface is not supported. It is up to the caller to decide
       * what to do in these cases.
       */
      library ERC165Checker {
          // As per the EIP-165 spec, no interface should ever match 0xffffffff
          bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
          /**
           * @dev Returns true if `account` supports the {IERC165} interface,
           */
          function supportsERC165(address account) internal view returns (bool) {
              // Any contract that implements ERC165 must explicitly indicate support of
              // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
              return
                  _supportsERC165Interface(account, type(IERC165).interfaceId) &&
                  !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
          }
          /**
           * @dev Returns true if `account` supports the interface defined by
           * `interfaceId`. Support for {IERC165} itself is queried automatically.
           *
           * See {IERC165-supportsInterface}.
           */
          function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
              // query support of both ERC165 as per the spec and support of _interfaceId
              return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);
          }
          /**
           * @dev Returns a boolean array where each value corresponds to the
           * interfaces passed in and whether they're supported or not. This allows
           * you to batch check interfaces for a contract where your expectation
           * is that some interfaces may not be supported.
           *
           * See {IERC165-supportsInterface}.
           *
           * _Available since v3.4._
           */
          function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)
              internal
              view
              returns (bool[] memory)
          {
              // an array of booleans corresponding to interfaceIds and whether they're supported or not
              bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
              // query support of ERC165 itself
              if (supportsERC165(account)) {
                  // query support of each interface in interfaceIds
                  for (uint256 i = 0; i < interfaceIds.length; i++) {
                      interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
                  }
              }
              return interfaceIdsSupported;
          }
          /**
           * @dev Returns true if `account` supports all the interfaces defined in
           * `interfaceIds`. Support for {IERC165} itself is queried automatically.
           *
           * Batch-querying can lead to gas savings by skipping repeated checks for
           * {IERC165} support.
           *
           * See {IERC165-supportsInterface}.
           */
          function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
              // query support of ERC165 itself
              if (!supportsERC165(account)) {
                  return false;
              }
              // query support of each interface in _interfaceIds
              for (uint256 i = 0; i < interfaceIds.length; i++) {
                  if (!_supportsERC165Interface(account, interfaceIds[i])) {
                      return false;
                  }
              }
              // all interfaces supported
              return true;
          }
          /**
           * @notice Query if a contract implements an interface, does not check ERC165 support
           * @param account The address of the contract to query for support of an interface
           * @param interfaceId The interface identifier, as specified in ERC-165
           * @return true if the contract at account indicates support of the interface with
           * identifier interfaceId, false otherwise
           * @dev Assumes that account contains a contract that supports ERC165, otherwise
           * the behavior of this method is undefined. This precondition can be checked
           * with {supportsERC165}.
           * Interface identification is specified in ERC-165.
           */
          function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
              // prepare call
              bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);
              // perform static call
              bool success;
              uint256 returnSize;
              uint256 returnValue;
              assembly {
                  success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
                  returnSize := returndatasize()
                  returnValue := mload(0x00)
              }
              return success && returnSize >= 0x20 && returnValue > 0;
          }
      }
      // SPDX-License-Identifier: MIT
      // 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);
      }
      // SPDX-License-Identifier: MIT
      pragma solidity 0.8.17;
      import "@openzeppelin/contracts/access/Ownable.sol";
      import "@openzeppelin/contracts/security/Pausable.sol";
      import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
      import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
      import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
      import "@openzeppelin/contracts/utils/Address.sol";
      import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
      contract Harvestooor is Ownable, Pausable, ReentrancyGuard, IERC721Receiver {
          using Address for address;
          using ERC165Checker for address;
          /**
           * Value each NFT will be harvested for (in wei).
           */
          uint256 public constant FIXED_NFT_VALUE = 1e10;
          /**
           * Maps a NFT to its prior owner.
           */
          mapping(address => mapping(uint256 => address)) private _priorOwnerByToken;
          /**
           * Struct which represent a ERC-721 NFT.
           */
          struct NFT {
              address tokenAddress;
              uint256 tokenId;
          }
          /**
           * Event emitted when ETH is sent to the contract.
           */
          event ValueReceived(address indexed sender, uint256 amount);
          /**
           * Event emitted when non fungible token(s) are harvested by the contract.
           */
          event TokensHarvested(address indexed sender, NFT[] tokens);
          /**
           * Event emitted when non fungible token(s) are repurchased.
           */
          event TokensRepurchased(address indexed sender, NFT[] tokens);
          /**
           * Returns the prior owner of a NFT given its address and tokenId.
           */
          function getPriorOwnerByToken(address tokenAddress, uint256 tokenId)
              external
              view
              returns (address)
          {
              return _priorOwnerByToken[tokenAddress][tokenId];
          }
          /**
           * Function which enables external consumers to sell
           * multiple ERC-721 NFTs to the contract. By calling this function,
           * the contract will transfer the tokens to itself (the contract)
           * and pay the sender a fixed amount of ETH for each token.
           */
          function sellTokens(NFT[] calldata tokens)
              external
              nonReentrant
              whenNotPaused
          {
              // Require 'tokens' to not be empty
              require(tokens.length > 0, "Harvestooor: 'tokens' must not be empty");
              address payable sender = payable(msg.sender);
              uint256 calculatedValue = tokens.length * FIXED_NFT_VALUE;
              // Require contract to contain enough ETH balance
              require(
                  address(this).balance >= calculatedValue,
                  "Harvestooor: Insufficient Balance"
              );
              for (uint256 i = 0; i < tokens.length; ++i) {
                  address tokenAddress = tokens[i].tokenAddress;
                  uint256 tokenId = tokens[i].tokenId;
                  // Sanity check NFT implements IERC721 interface
                  require(
                      tokenAddress.supportsInterface(type(IERC721).interfaceId),
                      "Harvestooor: Token must implement IERC721 interface"
                  );
                  IERC721 nft = IERC721(tokenAddress);
                  // Sanity check NFT is being sold by its owner
                  require(
                      nft.ownerOf(tokenId) == sender,
                      "Harvestooor: NFT must be sold by its owner"
                  );
                  // Write owner to ownerByToken map
                  _priorOwnerByToken[tokenAddress][tokenId] = sender;
                  // Safe Transfer NFT to self (this contract)
                  nft.safeTransferFrom(sender, address(this), tokenId);
              }
              // Emit event
              emit TokensHarvested(sender, tokens);
              // Transfer ETH to sender
              Address.sendValue(sender, calculatedValue);
          }
          /**
           * Function which enables external consumers to repurchase multiple
           * ERC-721 NFTs from the contract. By calling this function, the
           * contract will accept a fixed amount of ETH for every token
           * and transfer previously sold tokens back to their previous owner.
           */
          function repurchaseTokens(NFT[] calldata tokens)
              external
              payable
              nonReentrant
              whenNotPaused
          {
              // Require 'tokens' to not be empty
              require(tokens.length > 0, "Harvestooor: 'tokens' must not be empty");
              uint256 calculatedValue = tokens.length * FIXED_NFT_VALUE;
              // Require sender to have provided correct ETH value
              require(
                  msg.value == calculatedValue,
                  "Harvestooor: Transaction must include correct ETH value"
              );
              for (uint256 i = 0; i < tokens.length; ++i) {
                  address tokenAddress = tokens[i].tokenAddress;
                  uint256 tokenId = tokens[i].tokenId;
                  // Require NFT to have previously been sold to the contract
                  require(
                      _priorOwnerByToken[tokenAddress][tokenId] == msg.sender,
                      "Harvestooor: NFT must have been previously sold to the contract"
                  );
                  // Remove previous token from storage (must be done before token transfer)
                  delete _priorOwnerByToken[tokenAddress][tokenId];
                  // Transfer NFT back to sender (regular transfer)
                  IERC721 nft = IERC721(tokenAddress);
                  nft.transferFrom(address(this), msg.sender, tokenId);
              }
              // Emit event
              emit TokensRepurchased(msg.sender, tokens);
          }
          /**
           * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md#specification
           *
           * Always returns `IERC721Receiver.onERC721Received.selector`.
           */
          function onERC721Received(
              address,
              address from,
              uint256 tokenId,
              bytes memory
          ) public virtual override whenNotPaused returns (bytes4) {
              // Require NFT to have previously been sold to the contract (msg.sender is the NFT contract address)
              require(
                  _priorOwnerByToken[msg.sender][tokenId] == from,
                  "Harvestooor: NFT must have been previously sold to the contract"
              );
              return this.onERC721Received.selector;
          }
          /**
           * Pause the contract.
           */
          function pause() external nonReentrant onlyOwner whenNotPaused {
              _pause();
          }
          /**
           * Unpause the contract.
           */
          function unpause() external nonReentrant onlyOwner whenPaused {
              _unpause();
          }
          /**
           * Deposit ETH funds into the contract.
           */
          function deposit() external payable nonReentrant whenNotPaused {
              require(msg.value > 0, "Harvestooor: Value must be greater than zero");
              emit ValueReceived(msg.sender, msg.value);
          }
          /**
           * Withdrawal ETH funds to the given recipient address.
           */
          function withdraw(address payable recipient, uint256 amount)
              external
              nonReentrant
              onlyOwner
          {
              require(amount > 0, "Harvestooor: 'amount' must be greater than zero");
              require(
                  recipient != address(this),
                  "Harvestooor: 'recipient' must be an outside account"
              );
              Address.sendValue(recipient, amount);
          }
      }
      

      File 2 of 2: TheKindnessProject
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.8.9 <0.9.0;
      import 'erc721a/contracts/extensions/ERC721AQueryable.sol';
      import '@openzeppelin/contracts/access/Ownable.sol';
      import '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol';
      import '@openzeppelin/contracts/security/ReentrancyGuard.sol';
      contract TheKindnessProject is ERC721AQueryable, Ownable, ReentrancyGuard {
        using Strings for uint256;
        bytes32 public merkleRoot;
        mapping(address => bool) public whitelistClaimed;
        string public uriPrefix = '';
        string public uriSuffix = '.json';
        string public hiddenMetadataUri;
        
        uint256 public cost;
        uint256 public maxSupply;
        uint256 public maxMintAmountPerTx;
        bool public paused = true;
        bool public whitelistMintEnabled = false;
        bool public revealed = false;
        constructor(
          string memory _tokenName,
          string memory _tokenSymbol,
          uint256 _cost,
          uint256 _maxSupply,
          uint256 _maxMintAmountPerTx,
          string memory _hiddenMetadataUri
        ) ERC721A(_tokenName, _tokenSymbol) {
              _mint(0x9eB95d2ce7c806472EfAfB89Fc1D03466Ef516Cd, 1);
              _mint(0x9eB95d2ce7c806472EfAfB89Fc1D03466Ef516Cd, 1);
              _mint(0x473e12B41bC13d3Ac98C4d06cD549Ba8a704dbf1, 1);
              _mint(0x473e12B41bC13d3Ac98C4d06cD549Ba8a704dbf1, 1);
              _mint(0xE2a331eE86747E7C345fe299522f7f14174B432B, 1);
              _mint(0xE2a331eE86747E7C345fe299522f7f14174B432B, 1);
              _mint(0xE2a331eE86747E7C345fe299522f7f14174B432B, 1);
              _mint(0xE2a331eE86747E7C345fe299522f7f14174B432B, 1);
              _mint(0x4ac72cf2C23A1e00AE49749671690b3ea6C7D46f, 1);
              _mint(0x4ac72cf2C23A1e00AE49749671690b3ea6C7D46f, 1);
              _mint(0xC0468030c9Dd632Daa52E2221797ccC8a3F43922, 1);
              _mint(0xC0468030c9Dd632Daa52E2221797ccC8a3F43922, 1);
              _mint(0x35c28F43Ec7890E637F17BF34b379c422f5693D9, 1);
              _mint(0x33FE07b9458D34F777b7207b301Df93CCC8dBA67, 1);
              _mint(0x275bf84b73150F484B394F55b7bbe8ECDB5DDF5D, 1);
              _mint(0xf188eFBf912279715E46a1bDB378b994B45cd795, 1);
              _mint(0x5fdb0Fdeee546e95C552B1A1521441d8662d4298, 1);
              _mint(0x39820ac459E8d7CA56EC94BF1D0A7bE4A68AE3c1, 1);
              _mint(0x8118Aa67142Cf63AD5e9f7F755FE3eFC5A8790B7, 1);
              _mint(0x618e3e5707f62993695D8e4347495bb4c38466C2, 1);
              _mint(0xDf788eB75553b29cAB1A318dee77bF59567C2009, 1);
              _mint(0x397cC92Da013952925851FeF9aA0AFef150E4D8C, 1);
              _mint(0x6741a17fD1DB0431ce018032f98a532128e819e5, 1);
              _mint(0x3eFf592BA8A49f915e38B7274ea4Ff0AAbac8EfF, 1);
              _mint(0x7a640B5945954e257aE9B941c756BB99f0911fCd, 1);
              _mint(0x8C5Dc519418E6eD2778DcacEE2BDAB3708B75E38, 1);
              _mint(0xB3Cc8d3510F16BcAa7F3fa7241Fef86A3e890C97, 1);
              _mint(0xE06246A845aDbFe14DB01C8006Bb23b28951e7d3, 1);
              _mint(0x32579EcC5dD1e5e641cf7B72cb0016093C6C7964, 1);
              _mint(0xc6C5891CE448dB3E4155de1A0d85107f0a8bc6e3, 1);
              _mint(0xEAF6C384eBcD826DD6a5d8f305A40683A1cf77f0, 1);
              _mint(0x1c2Bd0cC868A72b0E38eF5aa10288256Bc535bDF, 1);
              _mint(0x32579EcC5dD1e5e641cf7B72cb0016093C6C7964, 1);
              _mint(0x1D182535A587BcFCF064765f30ACeB78e481a7F3, 1);
              _mint(0x36aC62a67127a6013B3861c8c229B3fdE92E897A, 1);
              _mint(0xF1Fa0bb46cCe9dbA707e68CB64D2FB159Ec1fEE5, 1);
              _mint(0x275bf84b73150F484B394F55b7bbe8ECDB5DDF5D, 1);
              _mint(0x2A2a159a96912733E40BDD721d2533eF5931274f, 1);
              _mint(0xCFebf82E85aC212153c65bC1FC48d2E9d2369698, 1);
              _mint(0xE06246A845aDbFe14DB01C8006Bb23b28951e7d3, 1);
              _mint(0x3b7fD269a8df5805c1664D6AcA85569fcb51885E, 1);
              _mint(0xAc93FAabf714BaC62657513cA4dA1eB4ae03b2B5, 1);
              _mint(0xF1Fa0bb46cCe9dbA707e68CB64D2FB159Ec1fEE5, 1);
              _mint(0x397cC92Da013952925851FeF9aA0AFef150E4D8C, 1);
              _mint(0x2A2a159a96912733E40BDD721d2533eF5931274f, 1);
              _mint(0xCBc3762F96B39a8282891e2b3eE685474798cc38, 1);
              _mint(0x591631285F17e0e3aE23c2695b632575B2455A1C, 1);
              _mint(0x15aDC7569505c1bf800DaaCD17A516A827eFF7B6, 1);
              _mint(0x1D182535A587BcFCF064765f30ACeB78e481a7F3, 1);
              _mint(0x4ac72cf2C23A1e00AE49749671690b3ea6C7D46f, 1);
              _mint(0x397cC92Da013952925851FeF9aA0AFef150E4D8C, 1);
              _mint(0x5AC784a8c43de48AfeCb5b6e20FAfF9ad2d2Ac10, 1);
              _mint(0xE2a331eE86747E7C345fe299522f7f14174B432B, 1);
              _mint(0x35c28F43Ec7890E637F17BF34b379c422f5693D9, 1);
              _mint(0x27f1d47abf7f4A21d6D97c30cfE7B08D4BFF30b4, 1);
              _mint(0x5e2979395b7C2F3275CeA442818Fc888215c5caf, 6); // insert TKP wallet for shelby, shan, night_owl, jamie, squishi, rekt
              _mint(0x149446A2c24Eb2faff15F3732f68eb9cd4362274, 1);
              _mint(0xF5DFdB8E86C55ca852a0c5b45F19E12be4B9f141, 1);
              _mint(0x591631285F17e0e3aE23c2695b632575B2455A1C, 2);
              _mint(0xCFebf82E85aC212153c65bC1FC48d2E9d2369698, 6);
              _mint(0x149446A2c24Eb2faff15F3732f68eb9cd4362274, 2);
              _mint(0xAc93FAabf714BaC62657513cA4dA1eB4ae03b2B5, 3);
              _mint(0x4ac72cf2C23A1e00AE49749671690b3ea6C7D46f, 3);
              _mint(0x35c28F43Ec7890E637F17BF34b379c422f5693D9, 1);
              _mint(0x36aC62a67127a6013B3861c8c229B3fdE92E897A, 2);
              _mint(0xEAF6C384eBcD826DD6a5d8f305A40683A1cf77f0, 5);
              _mint(0xF1Fa0bb46cCe9dbA707e68CB64D2FB159Ec1fEE5, 4);
              _mint(0xCBc3762F96B39a8282891e2b3eE685474798cc38, 1);
              _mint(0x2d197b021DA9Ae657Ebad44126b0C94eCE03F609, 1);
              _mint(0x397cC92Da013952925851FeF9aA0AFef150E4D8C, 15);
              _mint(0xdC93d75149756B060c431D9DBAa937Da67BDd6E7, 1);
              _mint(0x8533CF1CA87fa5CFF905BeBa585D1022B49Be828, 3);
              _mint(0xF79b434873b2762307099666C63D4c62b014C51E, 2);
              _mint(0x8e28e10660f9998472e61A5e8447452E7c80a94a, 1);
              _mint(0x772D6518C54eF2eB554fCeD24BbD705A5A1657e6, 1);
              _mint(0x1D915159Aeee1c9d71B4bE758301938B26be0966, 6);
              _mint(0x15aDC7569505c1bf800DaaCD17A516A827eFF7B6, 4);
              _mint(0x4E9edD87ADd0694398c430981d22fC17E39DFd6d, 1);
              _mint(0xB3Cc8d3510F16BcAa7F3fa7241Fef86A3e890C97, 4);
              _mint(0x1D182535A587BcFCF064765f30ACeB78e481a7F3, 6);
              _mint(0x67BE56FD6CE9703D2A3F24dB6B9b5F1fbd1e4386, 1);
              _mint(0xB7204e8B76900f69d8273B0b217700d2C525010D, 1);
              _mint(0x686CB9D88719E85aCA606797743A6cc0F7343d31, 1);
              _mint(0xc62E76a6Bb03E76b3152413C2B018752f8BE7606, 2);
              _mint(0x6132524899AbBDC16B7bC0bbbF1Fea77B2668365, 3);
              _mint(0x9c173A6F2f827895eBFC7a0dE4e9F7aDd89eAeB0, 1);
              _mint(0xe09815159ba25902a341AF4E7D47bFEF1e8c836A, 1);
              _mint(0x56868e255834782581677b195eb79573fE62fd87, 1);
              _mint(0xac39eA2Fb4Ee4Bb20121508FA0551ca77DC78C33, 1);
              _mint(0x44218C637fcf1a1CFC40a348685BfCf01BacE31A, 1);
              _mint(0x03Bbd6F1A1a712fa3B3f47412C72A8A74E3339a7, 1);
              _mint(0x837c3C3c7A5bfD37cf6eeb02f9417652d7CAFA55, 1);
              _mint(0x56AD9625afbD5Cb2c460bc26b2abBBF21Fe75bdA, 2);
              _mint(0xe8484605fa0887717e558A417751e643abb34D12, 1);
              _mint(0x5a7590079B0BF746c424B62249e33f6248B8EB74, 2);
              _mint(0x4dc4C46Fc1842f45113aE473809D2e88d8396d10, 1);
              _mint(0xAfa9abc254754fF6324E96cd8621D56109AFFB26, 2);
              _mint(0x5AC784a8c43de48AfeCb5b6e20FAfF9ad2d2Ac10, 2);
              _mint(0x5C34E725CcA657F02C1D81fb16142F6F0067689b, 1);
              _mint(0xFb9fc9Be1b1ade3138563748Ec3F3A5b4B9967c3, 2);
              _mint(0xa432DC73ee0d60c193c543dE42B6ae1e195020Ee, 2);
              _mint(0xeD694487CcaC768b04aed34700de75f96D584930, 1);
              _mint(0x45Ca078E0cD881096815C8c1Ff8fc3F0BDe58442, 1);
              _mint(0xa888A01aBf17Cf1f88C0E1Ca13674fa9F93b96A9, 1);
              _mint(0x1dec784B6C854222Fc7b2155791ccdcFf3e33C07, 2);
              _mint(0x0108afDCDd4EA85d7FE5f7f529fF1093Cb4D2Dc6, 1);
              _mint(0x97522bE0e661e257788067C989651e7AeE3B9261, 1);
              _mint(0x5236E9500b43c994bB9BbF15Cbb33b2B10F955Fa, 2);
              _mint(0xb33511A04C80544f82291727a93FEfA61b2a90dB, 1);
              _mint(0x6200769A96CA7054EB34D77230D6747e6Ec89D95, 2);
              _mint(0xbC3613715492a94f76AaaB581DcdFe61D8858b4b, 2);
              _mint(0x5e07fB29aA7fB940188eF1654D13818Dbc5aFCd9, 2);
              _mint(0xDB4E64e615B46F9dA2c48e7444F45CC5754F823F, 2);
              _mint(0x489C6Ece59631F254d1f4fc7D9Ac62F44281bDdA, 1);
              _mint(0xdDC57D029146698D59f4c465062c9900beF7dCbc, 1);
              _mint(0xB195679e7dAd1D236877A0594Da0A502E714C161, 1);
              _mint(0x0848E42Eae131dba9E4811f4C51895A7BB0CCC77, 1);
              _mint(0xC45670a6DB970296AC056734407a0CEC2719C04d, 1);
              _mint(0x0318D1d44208c468A3410914f50883e55304d145, 1);
              _mint(0x2e5A28037Fa6426b240d607e953BdfF90fe4a596, 1);
              _mint(0xc9eE9Fe68074Be6b5FE1826b5B0618Ccbcbda442, 2);
              _mint(0x4A9e7dd5b5f2987B85e197504e05E90563d60DA7, 1);
              _mint(0x64C07077c0dB13Cbf038050742E847432eA9ca2D, 1);
              _mint(0x2074424E6328ba40CEeA2F029aEf2662eA09c858, 1);
              _mint(0xa99aB610b9Bbac986F30882d8Bb84E55e3faD690, 1);
              _mint(0x5fdb0Fdeee546e95C552B1A1521441d8662d4298, 1);
              _mint(0xEd5957c426D46b979455CdE5178352660232C4de, 3);
              _mint(0x723CBC55DFb0Acab5A2fc5CF63AE322251dcB714, 1);
              _mint(0x13683B385ae5EC93024aa30a72274b219FdC3686, 1);
              _mint(0x1b6db55C7aa95F74f38B27D50eAee75A6a27d631, 1);
              _mint(0x32ea0b9ad4CEFdf67D19E90a9Be1a3Dd1627EA3a, 1);
              _mint(0xC1Dc4CeeF628D3eb4527E211F7691430f6e7E63C, 2);
              _mint(0xE2a331eE86747E7C345fe299522f7f14174B432B, 4);
              _mint(0xa23B1c4070c8FC3a9Bf7CcFC0ce0670d04f5F563, 2);
              _mint(0xc87c526d655Dd29D7c411F307c5c390f4d0d1B6c, 1);
              _mint(0xf7F012DF63CC03A63154f1c73CfaB3B94AcA3F21, 7);
              _mint(0x07C42831b30c68824f261C61074aC13F8Aa885d3, 1);
              _mint(0xb53f2b60A7ec0144D2C7C8fDE65E292c750559e2, 2);
              _mint(0xB3f6702aBa5a9681d825851A50Abe0f592f2fc0B, 1);
              _mint(0xf4FED1aFabC2A8ce096C32Cd57Fd86584Be9a568, 1);
              _mint(0xe2935EFd678C474fFf00fa307Befd26c6E78A321, 1);
              _mint(0x2eDcd8AC3F770dA56bba4735eB9369609d82945f, 2);
              _mint(0x934cceb5A43cDa9Ef7B2d78c6EcDd7712c725a5B, 4);
              _mint(0x473e12B41bC13d3Ac98C4d06cD549Ba8a704dbf1, 2);
              _mint(0xe3C6E58095a2Eec9eBd088166D14e3d5Ae00D097, 1);
              _mint(0xE06246A845aDbFe14DB01C8006Bb23b28951e7d3, 1);
              _mint(0xD43eBA46E10c08640caA952AB6d4ef11136F418E, 1);
              _mint(0x8C5Dc519418E6eD2778DcacEE2BDAB3708B75E38, 1);
              _mint(0x84b68db24d112c05b380A491f3658230cB74ABD2, 1);
              _mint(0x47FE71D055B82B55c988DaF0D95d3C0B27c0cf01, 1);
              _mint(0xb7Ee3cd42A17a2Ecc6a50ca5Fd60f6F7451C7a86, 1);
              _mint(0xC0468030c9Dd632Daa52E2221797ccC8a3F43922, 1);
              _mint(0x2718f35e4d0c2343463B1c44d93EfAd4c82b602c, 1);
              _mint(0x275bf84b73150F484B394F55b7bbe8ECDB5DDF5D, 1);
              _mint(0xfF49e90FCFBcF3eaf9e4c16573796B7d7C6a7A63, 1);
              _mint(0x33FE07b9458D34F777b7207b301Df93CCC8dBA67, 2);
              _mint(0x1c2Bd0cC868A72b0E38eF5aa10288256Bc535bDF, 1);
              _mint(0x2A2a159a96912733E40BDD721d2533eF5931274f, 3);
              _mint(0xDf788eB75553b29cAB1A318dee77bF59567C2009, 3);
              _mint(0xA17EDC44dAEf27f8C32E85D33938ae7464eBb297, 1);
              _mint(0x5f6266B796750Dc142F3806fa1c1c8c8C8864c82, 3);
              _mint(0xc6C5891CE448dB3E4155de1A0d85107f0a8bc6e3, 4);
              _mint(0x93390A8E616Bbfd0ACa53e5Bd4fC17Cb81260AE4, 3);
              _mint(0xD4F6396155DFFb7D37e696320B7e886B22e5fc97, 2);
              _mint(0x4DA894138fD4436624Aa3FBf85800B16450255d8, 1);
              _mint(0x6f99c30482601E8Ad021c7594B372A58291Ede60, 1);
              _mint(0x0e9D65F662bc5DEe370985f246d0510beB52697F, 1);
              _mint(0x2420ac35FE78a6eB5B2648354c06076a8b7A1d42, 1);
              _mint(0x09E46e182AB77e2320e7346602EEc1B1517f4002, 1);
              _mint(0x32579EcC5dD1e5e641cf7B72cb0016093C6C7964, 3);
              _mint(0xADe6b319FD30ac88079cd23D8B6D2Ce14ed24374, 1);
              _mint(0x93D56eD4Dd2E9F3f914b06E9aA9DD18bac07c6bc, 1);
              _mint(0xE4F14360E315025d686c1F9F0a8BA253b86B1e77, 1);
              _mint(0x7a640B5945954e257aE9B941c756BB99f0911fCd, 1);
              _mint(0x415aE86583C7df490a6237B62A755b6B43a993da, 2);
              _mint(0x6741a17fD1DB0431ce018032f98a532128e819e5, 1);
              _mint(0x976A3f5cc8e9B0160037CE316C0eC425a7732a7F, 1);
              _mint(0xedDeF7bB3989e38A72B0A8881Cb83B038D32669a, 1);
              _mint(0x8E1169fC7394AABd6253439cC584703041baB21a, 1);
              _mint(0x6D0BfAe82ef52A24732668066B00403bab457a89, 1);
              _mint(0x6B8c6fafCa4E8BA7708C86160c9438008bFC3ae7, 1);
              _mint(0xA19bba98145dE26643e572403fcB929037D58741, 1);
              _mint(0x1Dc6fc17986aD018991ADC89aEDA01eC1a00E572, 1);
              _mint(0x11c8678135658637fc510757cB26a1dE551565C3, 1);
              _mint(0xCeBCA66fDE0d8E1bE874ccB45893F5B680082A8f, 2);
              _mint(0xeb4c5F9fe9D2600EBbf81Aae782061ae801f533B, 1);
              _mint(0xCf0c4fc7420025dfC9Cbe94f3E31688F09517aB8, 1);
              _mint(0xa55Ec6DcE8798b039c45dF60123C4752c1d45C99, 1);
              _mint(0x91d559Bfc9A543062c212C1F9f43aDCA56dD7C58, 1);
              _mint(0x723B53EFC9B5e76fA9Ddff2ed14Fbe572D212C7a, 1);
              _mint(0x1054dEd2Cb78F21228402Cd610378C4b63D4A36A, 1);
              _mint(0x1D87FC655c44Ae85Eaa15807ce00433B7F36933d, 1);
              _mint(0x7983f91136900a15A9CB19088E98BC6f28dC8d53, 1);
              _mint(0xb4Ac5D5B88b733E1bC2cD0713Bc279B495123736, 1);
              _mint(0xd9B078117e8baCD60A63f6F77cf2B8aEF6f8B98B, 1);
              _mint(0x3eFf592BA8A49f915e38B7274ea4Ff0AAbac8EfF, 2);
              _mint(0x311A8a670525cDbF9fbe6c832efd87D71a79a3e8, 1);
              _mint(0x40690b3DF2fA52396783a32Ff36ae7c3307cD323, 1);
            setCost(_cost);
            maxSupply = _maxSupply;
            setMaxMintAmountPerTx(_maxMintAmountPerTx);
            setHiddenMetadataUri(_hiddenMetadataUri);
        }
        modifier mintCompliance(uint256 _mintAmount) {
          require(_mintAmount > 0 && _mintAmount <= maxMintAmountPerTx, 'Invalid mint amount!');
          require(totalSupply() + _mintAmount <= maxSupply, 'Max supply exceeded!');
          _;
        }
        function adminMint(address _destination, uint _quantity) external onlyOwner {
              require(_totalMinted() + _quantity <= maxSupply, "Not enough tokens left to mint");
              _mint(_destination, _quantity);
          }
        modifier mintPriceCompliance(uint256 _mintAmount) {
          require(msg.value >= cost * _mintAmount, 'Insufficient funds!');
          _;
        }
        function whitelistMint(uint256 _mintAmount, bytes32[] calldata _merkleProof) public payable mintCompliance(_mintAmount) mintPriceCompliance(_mintAmount) {
          // Verify whitelist requirements
          require(whitelistMintEnabled, 'The whitelist sale is not enabled!');
          require(!whitelistClaimed[_msgSender()], 'Address already claimed!');
          bytes32 leaf = keccak256(abi.encodePacked(_msgSender()));
          require(MerkleProof.verify(_merkleProof, merkleRoot, leaf), 'Invalid proof!');
          whitelistClaimed[_msgSender()] = true;
          _safeMint(_msgSender(), _mintAmount);
        }
        
        function mint(uint256 _mintAmount) public payable mintCompliance(_mintAmount) mintPriceCompliance(_mintAmount) {
          require(!paused, 'The contract is paused!');
          _safeMint(_msgSender(), _mintAmount);
        }
        
        function mintForAddress(uint256 _mintAmount, address _receiver) public mintCompliance(_mintAmount) onlyOwner {
          _safeMint(_receiver, _mintAmount);
        }
        function _startTokenId() internal view virtual override returns (uint256) {
          return 1;
        }
        function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
          require(_exists(_tokenId), 'ERC721Metadata: URI query for nonexistent token');
          if (revealed == false) {
            return hiddenMetadataUri;
          }
          string memory currentBaseURI = _baseURI();
          return bytes(currentBaseURI).length > 0
              ? string(abi.encodePacked(currentBaseURI, _tokenId.toString(), uriSuffix))
              : '';
        }
        function setRevealed(bool _state) public onlyOwner {
          revealed = _state;
        }
        function setCost(uint256 _cost) public onlyOwner {
          cost = _cost;
        }
        function setMaxMintAmountPerTx(uint256 _maxMintAmountPerTx) public onlyOwner {
          maxMintAmountPerTx = _maxMintAmountPerTx;
        }
        function setHiddenMetadataUri(string memory _hiddenMetadataUri) public onlyOwner {
          hiddenMetadataUri = _hiddenMetadataUri;
        }
        function setUriPrefix(string memory _uriPrefix) public onlyOwner {
          uriPrefix = _uriPrefix;
        }
        function setUriSuffix(string memory _uriSuffix) public onlyOwner {
          uriSuffix = _uriSuffix;
        }
        function setPaused(bool _state) public onlyOwner {
          paused = _state;
        }
        function setMerkleRoot(bytes32 _merkleRoot) public onlyOwner {
          merkleRoot = _merkleRoot;
        }
        function setWhitelistMintEnabled(bool _state) public onlyOwner {
          whitelistMintEnabled = _state;
        }
      // ======== WITHDRAW ========
          //ADDRESS LIST
          address TKP_WALLET = 0x4f5950bd06015E0420264D02655592016654845B;
          // FULL WITHDRAW
          function withdraw() public onlyOwner nonReentrant {
              uint256 balance = address(this).balance;
              require(balance > 0, "NO FUNDS AVAILABLE");
              payable(TKP_WALLET).transfer((balance * 100)/100);
          }
        function _baseURI() internal view virtual override returns (string memory) {
          return uriPrefix;
        }
      }
      // SPDX-License-Identifier: MIT
      // ERC721A Contracts v3.3.0
      // Creator: Chiru Labs
      pragma solidity ^0.8.4;
      import './IERC721AQueryable.sol';
      import '../ERC721A.sol';
      /**
       * @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 >= _currentIndex) {
                  return ownership;
              }
              ownership = _ownerships[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 = _currentIndex;
                  // Set `start = max(start, _startTokenId())`.
                  if (start < _startTokenId()) {
                      start = _startTokenId();
                  }
                  // Set `stop = min(stop, _currentIndex)`.
                  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 = _ownerships[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 = _ownerships[i];
                      if (ownership.burned) {
                          continue;
                      }
                      if (ownership.addr != address(0)) {
                          currOwnershipAddr = ownership.addr;
                      }
                      if (currOwnershipAddr == owner) {
                          tokenIds[tokenIdsIdx++] = i;
                      }
                  }
                  return tokenIds;
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @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);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev These functions deal with verification of Merkle Trees proofs.
       *
       * The proofs can be generated using the JavaScript library
       * https://github.com/miguelmota/merkletreejs[merkletreejs].
       * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
       *
       * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
       */
      library MerkleProof {
          /**
           * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
           * defined by `root`. For this, a `proof` must be provided, containing
           * sibling hashes on the branch from the leaf to the root of the tree. Each
           * pair of leaves and each pair of pre-images are assumed to be sorted.
           */
          function verify(
              bytes32[] memory proof,
              bytes32 root,
              bytes32 leaf
          ) internal pure returns (bool) {
              return processProof(proof, leaf) == root;
          }
          /**
           * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
           * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
           * hash matches the root of the tree. When processing the proof, the pairs
           * of leafs & pre-images are assumed to be sorted.
           *
           * _Available since v4.4._
           */
          function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
              bytes32 computedHash = leaf;
              for (uint256 i = 0; i < proof.length; i++) {
                  bytes32 proofElement = proof[i];
                  if (computedHash <= proofElement) {
                      // Hash(current computed hash + current element of the proof)
                      computedHash = _efficientHash(computedHash, proofElement);
                  } else {
                      // Hash(current element of the proof + current computed hash)
                      computedHash = _efficientHash(proofElement, computedHash);
                  }
              }
              return computedHash;
          }
          function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
              assembly {
                  mstore(0x00, a)
                  mstore(0x20, b)
                  value := keccak256(0x00, 0x40)
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Contract module that helps prevent reentrant calls to a function.
       *
       * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
       * available, which can be applied to functions to make sure there are no nested
       * (reentrant) calls to them.
       *
       * Note that because there is a single `nonReentrant` guard, functions marked as
       * `nonReentrant` may not call one another. This can be worked around by making
       * those functions `private`, and then adding `external` `nonReentrant` entry
       * points to them.
       *
       * TIP: If you would like to learn more about reentrancy and alternative ways
       * to protect against it, check out our blog post
       * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
       */
      abstract contract ReentrancyGuard {
          // Booleans are more expensive than uint256 or any type that takes up a full
          // word because each write operation emits an extra SLOAD to first read the
          // slot's contents, replace the bits taken up by the boolean, and then write
          // back. This is the compiler's defense against contract upgrades and
          // pointer aliasing, and it cannot be disabled.
          // The values being non-zero value makes deployment a bit more expensive,
          // but in exchange the refund on every call to nonReentrant will be lower in
          // amount. Since refunds are capped to a percentage of the total
          // transaction's gas, it is best to keep them low in cases like this one, to
          // increase the likelihood of the full refund coming into effect.
          uint256 private constant _NOT_ENTERED = 1;
          uint256 private constant _ENTERED = 2;
          uint256 private _status;
          constructor() {
              _status = _NOT_ENTERED;
          }
          /**
           * @dev Prevents a contract from calling itself, directly or indirectly.
           * Calling a `nonReentrant` function from another `nonReentrant`
           * function is not supported. It is possible to prevent this from happening
           * by making the `nonReentrant` function external, and making it call a
           * `private` function that does the actual work.
           */
          modifier nonReentrant() {
              // On the first call to nonReentrant, _notEntered will be true
              require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
              // Any calls to nonReentrant after this point will fail
              _status = _ENTERED;
              _;
              // By storing the original value once again, a refund is triggered (see
              // https://eips.ethereum.org/EIPS/eip-2200)
              _status = _NOT_ENTERED;
          }
      }
      // SPDX-License-Identifier: MIT
      // ERC721A Contracts v3.3.0
      // Creator: Chiru Labs
      pragma solidity ^0.8.4;
      import '../IERC721A.sol';
      /**
       * @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);
      }
      // SPDX-License-Identifier: MIT
      // ERC721A Contracts v3.3.0
      // Creator: Chiru Labs
      pragma solidity ^0.8.4;
      import './IERC721A.sol';
      import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
      import '@openzeppelin/contracts/utils/Address.sol';
      import '@openzeppelin/contracts/utils/Context.sol';
      import '@openzeppelin/contracts/utils/Strings.sol';
      import '@openzeppelin/contracts/utils/introspection/ERC165.sol';
      /**
       * @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 Context, ERC165, IERC721A {
          using Address for address;
          using Strings for uint256;
          // The tokenId of the next token to be minted.
          uint256 internal _currentIndex;
          // The number of tokens burned.
          uint256 internal _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 _ownershipOf implementation for details.
          mapping(uint256 => TokenOwnership) internal _ownerships;
          // Mapping owner address to address data
          mapping(address => AddressData) private _addressData;
          // 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();
          }
          /**
           * To change the starting tokenId, please override this function.
           */
          function _startTokenId() internal view virtual returns (uint256) {
              return 0;
          }
          /**
           * @dev Burned tokens are calculated here, use _totalMinted() if you want to count just minted tokens.
           */
          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();
              }
          }
          /**
           * 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 See {IERC165-supportsInterface}.
           */
          function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
              return
                  interfaceId == type(IERC721).interfaceId ||
                  interfaceId == type(IERC721Metadata).interfaceId ||
                  super.supportsInterface(interfaceId);
          }
          /**
           * @dev See {IERC721-balanceOf}.
           */
          function balanceOf(address owner) public view override returns (uint256) {
              if (owner == address(0)) revert BalanceQueryForZeroAddress();
              return uint256(_addressData[owner].balance);
          }
          /**
           * Returns the number of tokens minted by `owner`.
           */
          function _numberMinted(address owner) internal view returns (uint256) {
              return uint256(_addressData[owner].numberMinted);
          }
          /**
           * Returns the number of tokens burned by or on behalf of `owner`.
           */
          function _numberBurned(address owner) internal view returns (uint256) {
              return uint256(_addressData[owner].numberBurned);
          }
          /**
           * Returns the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
           */
          function _getAux(address owner) internal view returns (uint64) {
              return _addressData[owner].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 {
              _addressData[owner].aux = aux;
          }
          /**
           * 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) {
              uint256 curr = tokenId;
              unchecked {
                  if (_startTokenId() <= curr) if (curr < _currentIndex) {
                      TokenOwnership memory ownership = _ownerships[curr];
                      if (!ownership.burned) {
                          if (ownership.addr != address(0)) {
                              return ownership;
                          }
                          // 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.
                          while (true) {
                              curr--;
                              ownership = _ownerships[curr];
                              if (ownership.addr != address(0)) {
                                  return ownership;
                              }
                          }
                      }
                  }
              }
              revert OwnerQueryForNonexistentToken();
          }
          /**
           * @dev See {IERC721-ownerOf}.
           */
          function ownerOf(uint256 tokenId) public view override returns (address) {
              return _ownershipOf(tokenId).addr;
          }
          /**
           * @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, tokenId.toString())) : '';
          }
          /**
           * @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 See {IERC721-approve}.
           */
          function approve(address to, uint256 tokenId) public override {
              address owner = ERC721A.ownerOf(tokenId);
              if (to == owner) revert ApprovalToCurrentOwner();
              if (_msgSender() != owner) if(!isApprovedForAll(owner, _msgSender())) {
                  revert ApprovalCallerNotOwnerNorApproved();
              }
              _approve(to, tokenId, owner);
          }
          /**
           * @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 == _msgSender()) revert ApproveToCaller();
              _operatorApprovals[_msgSender()][operator] = approved;
              emit ApprovalForAll(_msgSender(), 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.isContract()) 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 && !_ownerships[tokenId].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 {
                  _addressData[to].balance += uint64(quantity);
                  _addressData[to].numberMinted += uint64(quantity);
                  _ownerships[startTokenId].addr = to;
                  _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);
                  uint256 updatedIndex = startTokenId;
                  uint256 end = updatedIndex + quantity;
                  if (to.isContract()) {
                      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 {
                  _addressData[to].balance += uint64(quantity);
                  _addressData[to].numberMinted += uint64(quantity);
                  _ownerships[startTokenId].addr = to;
                  _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);
                  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 {
              TokenOwnership memory prevOwnership = _ownershipOf(tokenId);
              if (prevOwnership.addr != from) revert TransferFromIncorrectOwner();
              bool isApprovedOrOwner = (_msgSender() == from ||
                  isApprovedForAll(from, _msgSender()) ||
                  getApproved(tokenId) == _msgSender());
              if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
              if (to == address(0)) revert TransferToZeroAddress();
              _beforeTokenTransfers(from, to, tokenId, 1);
              // Clear approvals from the previous owner
              _approve(address(0), tokenId, from);
              // 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 {
                  _addressData[from].balance -= 1;
                  _addressData[to].balance += 1;
                  TokenOwnership storage currSlot = _ownerships[tokenId];
                  currSlot.addr = to;
                  currSlot.startTimestamp = uint64(block.timestamp);
                  // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.
                  // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
                  uint256 nextTokenId = tokenId + 1;
                  TokenOwnership storage nextSlot = _ownerships[nextTokenId];
                  if (nextSlot.addr == address(0)) {
                      // This will suffice for checking _exists(nextTokenId),
                      // as a burned slot cannot contain the zero address.
                      if (nextTokenId != _currentIndex) {
                          nextSlot.addr = from;
                          nextSlot.startTimestamp = prevOwnership.startTimestamp;
                      }
                  }
              }
              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 {
              TokenOwnership memory prevOwnership = _ownershipOf(tokenId);
              address from = prevOwnership.addr;
              if (approvalCheck) {
                  bool isApprovedOrOwner = (_msgSender() == from ||
                      isApprovedForAll(from, _msgSender()) ||
                      getApproved(tokenId) == _msgSender());
                  if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
              }
              _beforeTokenTransfers(from, address(0), tokenId, 1);
              // Clear approvals from the previous owner
              _approve(address(0), tokenId, from);
              // 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 {
                  AddressData storage addressData = _addressData[from];
                  addressData.balance -= 1;
                  addressData.numberBurned += 1;
                  // Keep track of who burned the token, and the timestamp of burning.
                  TokenOwnership storage currSlot = _ownerships[tokenId];
                  currSlot.addr = from;
                  currSlot.startTimestamp = uint64(block.timestamp);
                  currSlot.burned = true;
                  // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it.
                  // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
                  uint256 nextTokenId = tokenId + 1;
                  TokenOwnership storage nextSlot = _ownerships[nextTokenId];
                  if (nextSlot.addr == address(0)) {
                      // This will suffice for checking _exists(nextTokenId),
                      // as a burned slot cannot contain the zero address.
                      if (nextTokenId != _currentIndex) {
                          nextSlot.addr = from;
                          nextSlot.startTimestamp = prevOwnership.startTimestamp;
                      }
                  }
              }
              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 Approve `to` to operate on `tokenId`
           *
           * Emits a {Approval} event.
           */
          function _approve(
              address to,
              uint256 tokenId,
              address owner
          ) private {
              _tokenApprovals[tokenId] = to;
              emit Approval(owner, to, tokenId);
          }
          /**
           * @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 IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                  return retval == 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 {}
      }
      // SPDX-License-Identifier: MIT
      // ERC721A Contracts v3.3.0
      // Creator: Chiru Labs
      pragma solidity ^0.8.4;
      import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
      import '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol';
      /**
       * @dev Interface of an ERC721A compliant contract.
       */
      interface IERC721A is IERC721, IERC721Metadata {
          /**
           * 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();
          // Compiler will pack this into a single 256bit word.
          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;
          }
          // Compiler will pack this into a single 256bit word.
          struct AddressData {
              // Realistically, 2**64-1 is more than enough.
              uint64 balance;
              // Keeps track of mint count with minimal overhead for tokenomics.
              uint64 numberMinted;
              // Keeps track of burn count with minimal overhead for tokenomics.
              uint64 numberBurned;
              // For miscellaneous variable(s) pertaining to the address
              // (e.g. number of whitelist mint slots used).
              // If there are multiple variables, please pack them into a uint64.
              uint64 aux;
          }
          /**
           * @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);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)
      pragma solidity ^0.8.0;
      import "../../utils/introspection/IERC165.sol";
      /**
       * @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`, 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 Returns the account approved for `tokenId` token.
           *
           * Requirements:
           *
           * - `tokenId` must exist.
           */
          function getApproved(uint256 tokenId) external view returns (address operator);
          /**
           * @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 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);
          /**
           * @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;
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
      pragma solidity ^0.8.0;
      import "../IERC721.sol";
      /**
       * @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);
      }
      // SPDX-License-Identifier: MIT
      // 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);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)
      pragma solidity ^0.8.0;
      /**
       * @title ERC721 token receiver interface
       * @dev Interface for any contract that wants to support safeTransfers
       * from ERC721 asset contracts.
       */
      interface IERC721Receiver {
          /**
           * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
           * by `operator` from `from`, this function is called.
           *
           * It must return its Solidity selector to confirm the token transfer.
           * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
           *
           * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
           */
          function onERC721Received(
              address operator,
              address from,
              uint256 tokenId,
              bytes calldata data
          ) external returns (bytes4);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
      pragma solidity ^0.8.1;
      /**
       * @dev Collection of functions related to the address type
       */
      library Address {
          /**
           * @dev Returns true if `account` is a contract.
           *
           * [IMPORTANT]
           * ====
           * It is unsafe to assume that an address for which this function returns
           * false is an externally-owned account (EOA) and not a contract.
           *
           * Among others, `isContract` will return false for the following
           * types of addresses:
           *
           *  - an externally-owned account
           *  - a contract in construction
           *  - an address where a contract will be created
           *  - an address where a contract lived, but was destroyed
           * ====
           *
           * [IMPORTANT]
           * ====
           * You shouldn't rely on `isContract` to protect against flash loan attacks!
           *
           * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
           * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
           * constructor.
           * ====
           */
          function isContract(address account) internal view returns (bool) {
              // This method relies on extcodesize/address.code.length, which returns 0
              // for contracts in construction, since the code is only stored at the end
              // of the constructor execution.
              return account.code.length > 0;
          }
          /**
           * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
           * `recipient`, forwarding all available gas and reverting on errors.
           *
           * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
           * of certain opcodes, possibly making contracts go over the 2300 gas limit
           * imposed by `transfer`, making them unable to receive funds via
           * `transfer`. {sendValue} removes this limitation.
           *
           * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
           *
           * IMPORTANT: because control is transferred to `recipient`, care must be
           * taken to not create reentrancy vulnerabilities. Consider using
           * {ReentrancyGuard} or the
           * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
           */
          function sendValue(address payable recipient, uint256 amount) internal {
              require(address(this).balance >= amount, "Address: insufficient balance");
              (bool success, ) = recipient.call{value: amount}("");
              require(success, "Address: unable to send value, recipient may have reverted");
          }
          /**
           * @dev Performs a Solidity function call using a low level `call`. A
           * plain `call` is an unsafe replacement for a function call: use this
           * function instead.
           *
           * If `target` reverts with a revert reason, it is bubbled up by this
           * function (like regular Solidity function calls).
           *
           * Returns the raw returned data. To convert to the expected return value,
           * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
           *
           * Requirements:
           *
           * - `target` must be a contract.
           * - calling `target` with `data` must not revert.
           *
           * _Available since v3.1._
           */
          function functionCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionCall(target, data, "Address: low-level call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
           * `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, 0, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but also transferring `value` wei to `target`.
           *
           * Requirements:
           *
           * - the calling contract must have an ETH balance of at least `value`.
           * - the called Solidity function must be `payable`.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
          }
          /**
           * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
           * with `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(address(this).balance >= value, "Address: insufficient balance for call");
              require(isContract(target), "Address: call to non-contract");
              (bool success, bytes memory returndata) = target.call{value: value}(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
              return functionStaticCall(target, data, "Address: low-level static call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal view returns (bytes memory) {
              require(isContract(target), "Address: static call to non-contract");
              (bool success, bytes memory returndata) = target.staticcall(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionDelegateCall(target, data, "Address: low-level delegate call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(isContract(target), "Address: delegate call to non-contract");
              (bool success, bytes memory returndata) = target.delegatecall(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
           * revert reason using the provided one.
           *
           * _Available since v4.3._
           */
          function verifyCallResult(
              bool success,
              bytes memory returndata,
              string memory errorMessage
          ) internal pure returns (bytes memory) {
              if (success) {
                  return returndata;
              } else {
                  // Look for revert reason and bubble it up if present
                  if (returndata.length > 0) {
                      // The easiest way to bubble the revert reason is using memory via assembly
                      assembly {
                          let returndata_size := mload(returndata)
                          revert(add(32, returndata), returndata_size)
                      }
                  } else {
                      revert(errorMessage);
                  }
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // 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;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev String operations.
       */
      library Strings {
          bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
          /**
           * @dev Converts a `uint256` to its ASCII `string` decimal representation.
           */
          function toString(uint256 value) internal pure returns (string memory) {
              // Inspired by OraclizeAPI's implementation - MIT licence
              // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
              if (value == 0) {
                  return "0";
              }
              uint256 temp = value;
              uint256 digits;
              while (temp != 0) {
                  digits++;
                  temp /= 10;
              }
              bytes memory buffer = new bytes(digits);
              while (value != 0) {
                  digits -= 1;
                  buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
                  value /= 10;
              }
              return string(buffer);
          }
          /**
           * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
           */
          function toHexString(uint256 value) internal pure returns (string memory) {
              if (value == 0) {
                  return "0x00";
              }
              uint256 temp = value;
              uint256 length = 0;
              while (temp != 0) {
                  length++;
                  temp >>= 8;
              }
              return toHexString(value, length);
          }
          /**
           * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
           */
          function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
              bytes memory buffer = new bytes(2 * length + 2);
              buffer[0] = "0";
              buffer[1] = "x";
              for (uint256 i = 2 * length + 1; i > 1; --i) {
                  buffer[i] = _HEX_SYMBOLS[value & 0xf];
                  value >>= 4;
              }
              require(value == 0, "Strings: hex length insufficient");
              return string(buffer);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
      pragma solidity ^0.8.0;
      import "./IERC165.sol";
      /**
       * @dev Implementation of the {IERC165} interface.
       *
       * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
       * for the additional interface id that will be supported. For example:
       *
       * ```solidity
       * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
       *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
       * }
       * ```
       *
       * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
       */
      abstract contract ERC165 is IERC165 {
          /**
           * @dev See {IERC165-supportsInterface}.
           */
          function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
              return interfaceId == type(IERC165).interfaceId;
          }
      }