ETH Price: $3,334.26 (-0.27%)

Token

Pets Oasis (PO)
 

Overview

Max Total Supply

3,127 PO

Holders

1,251

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
2 PO
0x07baa05335c7fa207b65d6c35926c21a4e9fa23e
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x316C6093...aD7683cf4
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
PetsOasis

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 10000 runs

Other Settings:
cancun EvmVersion
File 1 of 16 : PetsOasis.sol
// SPDX-License-Identifier: MIT

/**
 * Author: Lambdalf the White
 */
pragma solidity >=0.8.4 <0.9.0;

import { IERC721 } from "@lambdalf-dev/interfaces/IERC721.sol";
import { IERC721Enumerable } from "@lambdalf-dev/interfaces/IERC721Enumerable.sol";
import { IERC721Metadata } from "@lambdalf-dev/interfaces/IERC721Metadata.sol";
import { IERC173 } from "@lambdalf-dev/interfaces/IERC173.sol";
import { IERC165 } from "@lambdalf-dev/interfaces/IERC165.sol";
import { IERC2981 } from "@lambdalf-dev/interfaces/IERC2981.sol";
import { ITemplate } from "@lambdalf-dev/interfaces/ITemplate.sol";
import { IArrays } from "@lambdalf-dev/interfaces/IArrays.sol";
import { ERC721Batch } from "@lambdalf-dev/tokens/ERC721/ERC721Batch.sol";
import { ERC173 } from "@lambdalf-dev/utils/ERC173.sol";
import { ERC2981 } from "@lambdalf-dev/utils/ERC2981.sol";
import { Whitelist } from "@lambdalf-dev/utils/Whitelist.sol";

contract PetsOasis is IERC165, ERC721Batch, ERC173, ERC2981, ITemplate, IArrays {
  // **************************************
  // *****     STORAGE VARIABLES      *****
  // **************************************
  /// @dev Amount of NFTs reserved for team mint.
  uint256 public reserve;
  // **************************************

  // solhint-disable-next-line func-name-mixedcase
  constructor(
    uint256 reserve_,
    uint96 royaltyRate_,
    address royaltyRecipient_
  )
    ERC721Batch("Pets Oasis", "PO")
    ERC173(msg.sender)
    ERC2981(royaltyRecipient_, royaltyRate_)
  {
    reserve = reserve_;
    _setBaseUri("https://bafybeieenefkopvpnt2fvty5b4go2pyoqbkdspgnbflg44rlqpb2wua2zq.ipfs.nftstorage.link/");
  }

  // **************************************
  // *****       CONTRACT_OWNER       *****
  // **************************************
  /// @notice Mints `amounts_` tokens and transfers them to `accounts_`.
  ///
  /// @param accounts_ the list of accounts that will receive airdropped tokens
  /// @param amounts_ the amount of tokens each account will receive
  ///
  /// Requirements:
  ///
  /// - Caller must be the contract owner.
  /// - `accounts_` and `amounts_` must have the same length.
  /// - There must be enough tokens left in the reserve.
  function airdrop(address[] memory accounts_, uint256[] memory amounts_) public onlyOwner {
    uint256 _len_ = accounts_.length;
    if (_len_ != amounts_.length) {
      revert ARRAY_LENGTH_MISMATCH();
    }
    uint256 _count_;
    uint256 _totalQty_;
    while (_count_ < _len_) {
      _totalQty_ += amounts_[_count_];
      _mint(accounts_[_count_], amounts_[_count_]);
      unchecked {
        ++_count_;
      }
    }
    if (_totalQty_ > reserve) {
      revert NFT_MAX_RESERVE();
    }
    unchecked {
      reserve -= _totalQty_;
    }
  }

  // *******************
  // * IERC721Metadata *
  // *******************
  /// @notice Updates the baseUri for the tokens.
  ///
  /// @param newBaseUri_ the new baseUri for the tokens
  ///
  /// Requirements:
  ///
  /// - Caller must be the contract owner.
  function setBaseUri(string memory newBaseUri_) public onlyOwner {
    _setBaseUri(newBaseUri_);
  }
  // *******************

  // ************
  // * IERC2981 *
  // ************
  /// @dev Sets the royalty rate to `newRoyaltyRate_` and the royalty recipient to `newRoyaltyRecipient_`.
  ///
  /// @param newRoyaltyRecipient_ the address that will receive royalty payments
  /// @param newRoyaltyRate_ the percentage of the sale price that will be taken off as royalties,
  ///   expressed in Basis Points (100 BP = 1%)
  ///
  /// Requirements:
  ///
  /// - Caller must be the contract owner.
  /// - `newRoyaltyRate_` cannot be higher than {ROYALTY_BASE};
  function setRoyaltyInfo(address newRoyaltyRecipient_, uint96 newRoyaltyRate_) public onlyOwner {
    _setRoyaltyInfo(newRoyaltyRecipient_, newRoyaltyRate_);
  }
  // ************
  // **************************************

  // **************************************
  // *****            VIEW            *****
  // **************************************
  // *******************
  // * IERC721Metadata *
  // *******************
  /// @dev A distinct Uniform Resource Identifier (URI) for a given asset.
  ///
  /// @param tokenId_ the NFT that has been approved
  ///
  /// @return uri the URI of the token
  ///
  /// Requirements:
  ///
  /// - `tokenId_` must exist.

  function tokenURI(uint256 tokenId_) public view virtual override exists(tokenId_) returns (string memory uri) {
    return string(abi.encodePacked(_baseUri, _toString(tokenId_), ".png"));
  }
  // *******************

  // ***********
  // * IERC165 *
  // ***********
  /// @dev Query if a contract implements an interface.
  /// @dev see https://eips.ethereum.org/EIPS/eip-165
  ///
  /// @param interfaceId_ the interface identifier, as specified in ERC-165
  ///
  /// @return bool true if the contract implements the specified interface, false otherwise
  ///
  /// Requirements:
  ///
  /// - This function must use less than 30,000 gas.
  function supportsInterface(bytes4 interfaceId_) public pure override returns (bool) {
    return interfaceId_ == type(IERC721).interfaceId || interfaceId_ == type(IERC721Enumerable).interfaceId
      || interfaceId_ == type(IERC721Metadata).interfaceId || interfaceId_ == type(IERC173).interfaceId
      || interfaceId_ == type(IERC165).interfaceId || interfaceId_ == type(IERC2981).interfaceId;
  }
  // ***********
  // **************************************
}

File 2 of 16 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

// import "./IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-721[EIP].
 *   Note: the ERC-165 identifier for this interface is 0x80ac58cd.
 */
interface IERC721 { /* is IERC165 */
  // **************************************
  // *****           ERRORS           *****
  // **************************************
  /// @dev Thrown when operator is not allowed to manage tokenId.
  error IERC721_CALLER_NOT_APPROVED();
  /// @dev Thrown when user tries to approve themselves for managing a token they own.
  error IERC721_INVALID_APPROVAL();
  /// @dev Thrown when a token is being transferred to a contract unable to handle it or the zero address.
  error IERC721_INVALID_RECEIVER();
  /// @dev Thrown when checking ownership of the wrong token owner.
  error IERC721_INVALID_TOKEN_OWNER();
  /// @dev Thrown when the requested token does not exist.
  error IERC721_NONEXISTANT_TOKEN();
  // **************************************

  // **************************************
  // *****           EVENTS           *****
  // **************************************
  /// @dev This emits when the approved address for an NFT is changed or reaffirmed.
  ///   The zero address indicates there is no approved address.
  ///   When a Transfer event emits, this also indicates that the approved address for that NFT (if any) is reset to
  /// none.
  ///
  /// @param owner address that owns the token
  /// @param approved address that is allowed to manage the token
  /// @param tokenId identifier of the token being approved
  event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
  /// @dev This emits when an operator is enabled or disabled for an owner. The operator can manage all NFTs of the
  /// owner.
  ///
  /// @param owner address that owns the tokens
  /// @param operator address that is allowed or not to manage the tokens
  /// @param approved whether the operator is allowed or not
  event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
  /// @dev This emits when ownership of any NFT changes by any mechanism.
  ///   This event emits when NFTs are created (`from` == 0) and destroyed (`to` == 0).
  ///   Exception: during contract creation, any number of NFTs may be created and assigned without emitting Transfer.
  ///   At the time of any transfer, the approved address for that NFT (if any) is reset to none.
  ///
  /// @param from address the token is being transferred from
  /// @param to address the token is being transferred to
  /// @param tokenId identifier of the token being transferred
  event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
  // **************************************

  // **************************************
  // *****           PUBLIC           *****
  // **************************************
  /// @notice Change or reaffirm the approved address for an NFT
  /// @dev The zero address indicates there is no approved address.
  ///   Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.
  function approve(address approved_, uint256 tokenId_) external;
  /// @notice Transfers the ownership of an NFT from one address to another address
  /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this
  /// NFT.
  ///   Throws if `from_` is not the current owner.
  ///   Throws if `to_` is the zero address.
  ///   Throws if `tokenId_` is not a valid NFT.
  ///   When transfer is complete, this function checks if `to_` is a smart contract (code size > 0).
  ///   If so, it calls {onERC721Received} on `to_` and throws if the return value is not
  ///   `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
  function safeTransferFrom(address from_, address to_, uint256 tokenId_, bytes calldata data_) external;
  /// @notice Transfers the ownership of an NFT from one address to another address
  /// @dev This works identically to the other function with an extra data parameter,
  ///   except this function just sets data to "".
  function safeTransferFrom(address from_, address to_, uint256 tokenId_) external;
  /// @notice Enable or disable approval for a third party ("operator") to manage all of `msg.sender`'s assets.
  /// @dev Emits the ApprovalForAll event. The contract MUST allow multiple operators per owner.
  function setApprovalForAll(address operator_, bool approved_) external;
  /// @notice Transfer ownership of an NFT.
  ///   The caller is responsible to confirm that `to_` is capable of receiving nfts or
  ///   else they may be permanently lost
  /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this
  /// NFT.
  ///   Throws if `from_` is not the current owner.
  ///   Throws if `to_` is the zero address.
  ///   Throws if `tokenId_` is not a valid NFT.
  function transferFrom(address from_, address to_, uint256 tokenId_) external;
  // **************************************

  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @notice Count all NFTs assigned to an owner
  /// @dev NFTs assigned to the zero address are considered invalid. Throws for queries about the zero address.
  function balanceOf(address owner_) external view returns (uint256);
  /// @notice Get the approved address for a single NFT
  /// @dev Throws if `tokenId_` is not a valid NFT.
  function getApproved(uint256 tokenId_) external view returns (address);
  /// @notice Query if an address is an authorized operator for another address
  function isApprovedForAll(address owner_, address operator_) external view returns (bool);
  /// @notice Find the owner of an NFT
  /// @dev NFTs assigned to zero address are considered invalid, and queries
  ///  about them do throw.
  function ownerOf(uint256 tokenId_) external view returns (address);
  // **************************************
}

File 3 of 16 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

// import "./IERC721.sol";

/**
 * @dev Required interface of an ERC721 compliant contract, optional enumeration extension, as defined in the
 * https://eips.ethereum.org/EIPS/eip-721[EIP].
 *   Note: the ERC-165 identifier for this interface is 0x780e9d63.
 */
interface IERC721Enumerable { /* is IERC721 */
  // **************************************
  // *****           ERRORS           *****
  // **************************************
  /// @dev Thrown when trying to get the token at an index that does not exist.
  error IERC721Enumerable_INDEX_OUT_OF_BOUNDS();
  /// @dev Thrown when trying to get the token owned by tokenOwner at an index that does not exist.
  error IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS();
  // **************************************

  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @dev Enumerate valid NFTs
  ///   Throws if `index_` >= {totalSupply()}.
  function tokenByIndex(uint256 index_) external view returns (uint256);
  /// @dev Enumerate NFTs assigned to an owner
  ///   Throws if `index_` >= {balanceOf(owner_)} or if `owner_` is the zero address, representing invalid NFTs.
  function tokenOfOwnerByIndex(address owner_, uint256 index_) external view returns (uint256);
  /// @dev Count NFTs tracked by this contract
  function totalSupply() external view returns (uint256);
  // **************************************
}

File 4 of 16 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

// import "./IERC721.sol";

/**
 * @dev Required interface of an ERC721 compliant contract, optional metadata extension, as defined in the
 * https://eips.ethereum.org/EIPS/eip-721[EIP].
 *   Note: the ERC-165 identifier for this interface is 0x5b5e139f.
 */
interface IERC721Metadata { /* is IERC721 */
  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @dev A descriptive name for a collection of NFTs in this contract
  function name() external view returns (string memory);
  /// @dev An abbreviated name for NFTs in this contract
  function symbol() external view returns (string memory);
  /// @dev A distinct Uniform Resource Identifier (URI) for a given asset.
  ///   Throws if `tokenId_` is not a valid NFT. URIs are defined in RFC 3986.
  ///   The URI may point to a JSON file that conforms to the "ERC721 Metadata JSON Schema".
  function tokenURI(uint256 tokenId_) external view returns (string memory);
  // **************************************
}

File 5 of 16 : IERC173.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

// import "./IERC165.sol";

/**
 * @dev Required interface of an ERC173 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-173[EIP].
 *   Note: the ERC-165 identifier for this interface is 0x7f5828d0.
 */
interface IERC173 { /* is IERC165 */
  // **************************************
  // *****           ERRORS           *****
  // **************************************
  /// @dev Thrown when operator is not the contract owner.
  error IERC173_NOT_OWNER();
  // **************************************

  // **************************************
  // *****           EVENTS           *****
  // **************************************
  /// @dev This emits when ownership of a contract changes.
  ///
  /// @param previousOwner the previous contract owner
  /// @param newOwner the new contract owner
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
  // **************************************

  // **************************************
  // *****       CONTRACT_OWNER       *****
  // **************************************
  /// @dev Set the address of the new owner of the contract.
  ///   Set `newOwner_` to address(0) to renounce any ownership.
  function transferOwnership(address newOwner_) external;
  // **************************************

  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @dev Returns the address of the owner.
  function owner() external view returns (address);
  // **************************************
}

File 6 of 16 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

/**
 * @dev Required interface of an ERC165 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *   Note: the ERC-165 identifier for this interface is 0x01ffc9a7.
 */
interface IERC165 {
  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @dev Returns if a contract implements an interface.
  ///   Interface identification is specified in ERC-165. This function uses less than 30,000 gas.
  function supportsInterface(bytes4 interfaceId_) external view returns (bool);
  // **************************************
}

File 7 of 16 : IERC2981.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

// import "./IERC165.sol";

/**
 * @dev Required interface of an ERC2981 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-2981[EIP].
 *   Note: the ERC-165 identifier for this interface is 0x2a55205a.
 */
interface IERC2981 { /* is IERC165 */
  // **************************************
  // *****           ERRORS           *****
  // **************************************
  /// @dev Thrown when the desired royalty rate is higher than 10,000
  error IERC2981_INVALID_ROYALTIES();
  // **************************************

  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @dev Called with the sale price to determine how much royalty is owed and to whom.
  function royaltyInfo(
    uint256 tokenId_,
    uint256 salePrice_
  )
    external
    view
    returns (address receiver, uint256 royaltyAmount);
  // **************************************
}

File 8 of 16 : ITemplate.sol
// SPDX-License-Identifier: MIT

/**
 * Team: Asteria Labs
 * Author: Lambdalf the White
 */
pragma solidity >=0.8.4 <0.9.0;

interface ITemplate {
  // **************************************
  // *****           ERRORS           *****
  // **************************************
  /// @dev Thrown when a function is called with the wrong contract state.
  error CONTRACT_STATE_INCORRECT();
  /// @dev Thrown when trying to set the contract state to an invalid value.
  error CONTRACT_STATE_INVALID();
  /// @dev Thrown when an incorrect amount of eth is being sent for a payable operation.
  error ETHER_INCORRECT_PRICE();
  /// @dev Thrown when trying to withdraw from the contract with no balance.
  error ETHER_NO_BALANCE();
  /// @dev Thrown when contract fails to send ether to recipient.
  error ETHER_TRANSFER_FAIL();
  /// @dev Thrown when trying to mint 0 token.
  error NFT_INVALID_QTY();
  /// @dev Thrown when trying to set reserve to an invalid amount.
  error NFT_INVALID_RESERVE();
  /// @dev Thrown when trying to set max supply to an invalid amount.
  error NFT_INVALID_SUPPLY();
  /// @dev Thrown when trying to mint more tokens than the max allowed per transaction.
  error NFT_MAX_BATCH();
  /// @dev Thrown when trying to mint more tokens from the reserve than the amount left.
  error NFT_MAX_RESERVE();
  /// @dev Thrown when trying to mint more tokens than the amount left to be minted (except reserve).
  error NFT_MINTED_OUT();
  /// @dev Thrown when trying to call a non existant function.
  error UNKNOWN();
  // **************************************

  // **************************************
  // *****           EVENTS           *****
  // **************************************
  /// @dev Emitted when the sale state changes
  ///
  /// @param previousState the previous state of the contract
  /// @param newState the new state of the contract
  event ContractStateChanged(uint8 indexed previousState, uint8 indexed newState);
  // **************************************
}

File 9 of 16 : IArrays.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

interface IArrays {
  // **************************************
  // *****           ERRORS           *****
  // **************************************
  /// @dev Thrown when two related arrays have different lengths.
  error ARRAY_LENGTH_MISMATCH();
  // **************************************
}

File 10 of 16 : ERC721Batch.sol
// SPDX-License-Identifier: MIT

/**
 * Author: Lambdalf the White
 */
pragma solidity ^0.8.17;

import { IERC721 } from "../../interfaces/IERC721.sol";
import { IERC721Metadata } from "../../interfaces/IERC721Metadata.sol";
import { IERC721Enumerable } from "../../interfaces/IERC721Enumerable.sol";
import { IERC721Receiver } from "../../interfaces/IERC721Receiver.sol";
import { IERC2309 } from "../../interfaces/IERC2309.sol";

/// @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard.
/// @dev This contract does not implement ERC165, unlike the ERC721 specification recommends,
///   to simplify inheritance tree. Remember to implement it in the final contract.
///   Note: this implementation has a very inefficient {balanceOf} function.
abstract contract ERC721Batch is IERC721, IERC721Metadata, IERC721Enumerable, IERC2309 {
  // **************************************
  // *****     STORAGE VARIABLES      *****
  // **************************************
  // ***********
  // * IERC721 *
  // ***********
  /// @dev Identifier of the next token to be minted
  uint256 internal _nextId = 1;
  /// @dev Token ID mapped to approved address
  mapping(uint256 => address) internal _approvals;
  /// @dev Token owner mapped to operator approvals
  mapping(address => mapping(address => bool)) internal _operatorApprovals;
  /// @dev List of owner addresses
  mapping(uint256 => address) internal _owners;
  // ***********

  // *******************
  // * IERC721Metadata *
  // *******************
  /// @dev The token's base URI.
  string internal _baseUri;
  /// @dev The name of the tokens, for token trackers.
  string internal _name;
  /// @dev The symbol of the tokens, for token trackers.
  string internal _symbol;
  // *******************
  // **************************************

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

  // **************************************
  // *****          MODIFIER          *****
  // **************************************
  // ***********
  // * IERC721 *
  // ***********
  /// @dev Throws if `tokenId_` doesn't exist.
  /// A token exists if it has been minted and is not owned by the zero address.
  ///
  /// @param tokenId_ identifier of the NFT being referenced
  modifier exists(uint256 tokenId_) {
    if (!_exists(tokenId_)) {
      revert IERC721_NONEXISTANT_TOKEN();
    }
    _;
  }
  // ***********
  // **************************************

  // **************************************
  // *****           PUBLIC           *****
  // **************************************
  // ***********
  // * IERC721 *
  // ***********
  /// @dev Gives permission to `to_` to transfer the token number `tokenId_` on behalf of its owner.
  /// 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.
  ///
  /// @param to_ The new approved NFT controller
  /// @param tokenId_ The NFT to approve
  ///
  /// Requirements:
  ///
  /// - The token number `tokenId_` must exist.
  /// - The caller must own the token or be an approved operator.
  /// - Must emit an {Approval} event.
  function approve(address to_, uint256 tokenId_) public virtual override {
    address _tokenOwner_ = ownerOf(tokenId_);
    if (to_ == _tokenOwner_) {
      revert IERC721_INVALID_APPROVAL();
    }
    bool _isApproved_ = isApprovedForAll(_tokenOwner_, msg.sender);
    if (msg.sender != _tokenOwner_ && !_isApproved_) {
      revert IERC721_CALLER_NOT_APPROVED();
    }
    _approvals[tokenId_] = to_;
    emit Approval(_tokenOwner_, to_, tokenId_);
  }
  /// @dev Transfers the token number `tokenId_` from `from_` to `to_`.
  ///
  /// @param from_ The current owner of the NFT
  /// @param to_ The new owner
  /// @param tokenId_ identifier of the NFT being referenced
  ///
  /// Requirements:
  ///
  /// - The token number `tokenId_` must exist.
  /// - `from_` must be the token owner.
  /// - The caller must own the token or be an approved operator.
  /// - `to_` must not be the zero address.
  /// - If `to_` is a contract, it must implement {IERC721Receiver-onERC721Received} with a return value of
  /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`,
  /// - Must emit a {Transfer} event.

  function safeTransferFrom(address from_, address to_, uint256 tokenId_) public virtual override {
    safeTransferFrom(from_, to_, tokenId_, "");
  }
  /// @dev Transfers the token number `tokenId_` from `from_` to `to_`.
  ///
  /// @param from_ The current owner of the NFT
  /// @param to_ The new owner
  /// @param tokenId_ identifier of the NFT being referenced
  /// @param data_ Additional data with no specified format, sent in call to `to_`
  ///
  /// Requirements:
  ///
  /// - The token number `tokenId_` must exist.
  /// - `from_` must be the token owner.
  /// - The caller must own the token or be an approved operator.
  /// - `to_` must not be the zero address.
  /// - If `to_` is a contract, it must implement {IERC721Receiver-onERC721Received} with a return value of
  /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`,
  /// - Must emit a {Transfer} event.

  function safeTransferFrom(address from_, address to_, uint256 tokenId_, bytes memory data_) public virtual override {
    transferFrom(from_, to_, tokenId_);
    if (!_checkOnERC721Received(from_, to_, tokenId_, data_)) {
      revert IERC721_INVALID_RECEIVER();
    }
  }
  /// @dev Allows or disallows `operator_` to manage the caller's tokens on their behalf.
  ///
  /// @param operator_ Address to add to the set of authorized operators
  /// @param approved_ True if the operator is approved, false to revoke approval
  ///
  /// Requirements:
  ///
  /// - Must emit an {ApprovalForAll} event.

  function setApprovalForAll(address operator_, bool approved_) public virtual override {
    if (operator_ == msg.sender) {
      revert IERC721_INVALID_APPROVAL();
    }
    _operatorApprovals[msg.sender][operator_] = approved_;
    emit ApprovalForAll(msg.sender, operator_, approved_);
  }
  /// @dev Transfers the token number `tokenId_` from `from_` to `to_`.
  ///
  /// @param from_ the current owner of the NFT
  /// @param to_ the new owner
  /// @param tokenId_ identifier of the NFT being referenced
  ///
  /// Requirements:
  ///
  /// - The token number `tokenId_` must exist.
  /// - `from_` must be the token owner.
  /// - The caller must own the token or be an approved operator.
  /// - `to_` must not be the zero address.
  /// - Must emit a {Transfer} event.

  function transferFrom(address from_, address to_, uint256 tokenId_) public virtual override {
    if (to_ == address(0)) {
      revert IERC721_INVALID_RECEIVER();
    }
    address _tokenOwner_ = ownerOf(tokenId_);
    if (from_ != _tokenOwner_) {
      revert IERC721_INVALID_TOKEN_OWNER();
    }
    if (!_isApprovedOrOwner(_tokenOwner_, msg.sender, tokenId_)) {
      revert IERC721_CALLER_NOT_APPROVED();
    }
    _transfer(from_, to_, tokenId_);
  }
  // ***********
  // **************************************

  // **************************************
  // *****            VIEW            *****
  // **************************************
  // ***********
  // * IERC721 *
  // ***********
  /// @dev Returns the number of tokens in `tokenOwner_`'s account.
  ///
  /// @param tokenOwner_ address that owns tokens
  ///
  /// @return ownerBalance the nomber of tokens owned by `tokenOwner_`
  ///
  /// Requirements:
  ///
  /// - `tokenOwner_` must not be the zero address
  function balanceOf(address tokenOwner_) public view virtual override returns (uint256 ownerBalance) {
    if (tokenOwner_ == address(0)) {
      revert IERC721_INVALID_TOKEN_OWNER();
    }
    address _currentTokenOwner_;
    uint256 _index_ = 1;
    while (_index_ < _nextId) {
      if (_exists(_index_)) {
        if (_owners[_index_] != address(0)) {
          _currentTokenOwner_ = _owners[_index_];
        }
        if (tokenOwner_ == _currentTokenOwner_) {
          unchecked {
            ++ownerBalance;
          }
        }
      }
      unchecked {
        ++_index_;
      }
    }
  }
  /// @dev Returns the address that has been specifically allowed to manage `tokenId_` on behalf of its owner.
  ///
  /// @param tokenId_ the NFT that has been approved
  ///
  /// @return approved the address allowed to manage `tokenId_`
  ///
  /// Requirements:
  ///
  /// - `tokenId_` must exist.
  ///
  /// Note: See {Approve}

  function getApproved(uint256 tokenId_) public view virtual override exists(tokenId_) returns (address approved) {
    return _approvals[tokenId_];
  }
  /// @dev Returns whether `operator_` is allowed to manage tokens on behalf of `tokenOwner_`.
  ///
  /// @param tokenOwner_ address that owns tokens
  /// @param operator_ address that tries to manage tokens
  ///
  /// @return isApproved whether `operator_` is allowed to handle `tokenOwner`'s tokens
  ///
  /// Note: See {setApprovalForAll}

  function isApprovedForAll(
    address tokenOwner_,
    address operator_
  )
    public
    view
    virtual
    override
    returns (bool isApproved)
  {
    return _operatorApprovals[tokenOwner_][operator_];
  }
  /// @dev Returns the owner of the token number `tokenId_`.
  ///
  /// @param tokenId_ the NFT to verify ownership of
  ///
  /// @return tokenOwner the owner of token number `tokenId_`
  ///
  /// Requirements:
  ///
  /// - `tokenId_` must exist.

  function ownerOf(uint256 tokenId_) public view virtual override exists(tokenId_) returns (address tokenOwner) {
    uint256 _tokenId_ = tokenId_;
    tokenOwner = _owners[_tokenId_];
    while (tokenOwner == address(0)) {
      unchecked {
        --_tokenId_;
      }
      tokenOwner = _owners[_tokenId_];
    }
  }
  // ***********

  // *********************
  // * IERC721Enumerable *
  // *********************
  /// @dev Enumerate valid NFTs
  ///
  /// @param index_ the index requested
  ///
  /// @return tokenId the identifier of the token at the specified index
  ///
  /// Requirements:
  ///
  /// - `index_` must be less than {totalSupply()}
  function tokenByIndex(uint256 index_) public view virtual override returns (uint256) {
    if (index_ >= _nextId - 1) {
      revert IERC721Enumerable_INDEX_OUT_OF_BOUNDS();
    }
    return index_ + 1;
  }
  /// @dev Enumerate NFTs assigned to an owner
  ///
  /// @param tokenOwner_ the address requested
  /// @param index_ the index requested
  ///
  /// @return tokenId the identifier of the token at the specified index
  ///
  /// Requirements:
  ///
  /// - `index_` must be less than {balanceOf(tokenOwner_)}
  /// - `tokenOwner_` must not be the zero address

  function tokenOfOwnerByIndex(address tokenOwner_, uint256 index_) public view virtual override returns (uint256) {
    if (tokenOwner_ == address(0)) {
      revert IERC721_INVALID_TOKEN_OWNER();
    }
    address _currentTokenOwner_;
    uint256 _index_ = 1;
    uint256 _ownerBalance_;
    while (_index_ < _nextId) {
      if (_exists(_index_)) {
        if (_owners[_index_] != address(0)) {
          _currentTokenOwner_ = _owners[_index_];
        }
        if (tokenOwner_ == _currentTokenOwner_) {
          if (index_ == _ownerBalance_) {
            return _index_;
          }
          unchecked {
            ++_ownerBalance_;
          }
        }
      }
      unchecked {
        ++_index_;
      }
    }
    revert IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS();
  }
  /// @notice Count NFTs tracked by this contract
  ///
  /// @return supply the number of NFTs in existence

  function totalSupply() public view virtual override returns (uint256 supply) {
    return _nextId - 1;
  }
  // *********************

  // *******************
  // * IERC721Metadata *
  // *******************
  /// @dev A descriptive name for a collection of NFTs in this contract
  ///
  /// @return tokenName The descriptive name of the NFTs
  function name() public view virtual override returns (string memory tokenName) {
    return _name;
  }
  /// @dev An abbreviated name for NFTs in this contract
  ///
  /// @return tokenSymbol The abbreviated name of the NFTs

  function symbol() public view virtual override returns (string memory tokenSymbol) {
    return _symbol;
  }
  /// @dev A distinct Uniform Resource Identifier (URI) for a given asset.
  ///
  /// @param tokenId_ the NFT that has been approved
  ///
  /// @return uri the URI of the token
  ///
  /// Requirements:
  ///
  /// - `tokenId_` must exist.

  function tokenURI(uint256 tokenId_) public view virtual override exists(tokenId_) returns (string memory uri) {
    return /*bytes(_baseUri).length > 0 ?*/ string(abi.encodePacked(_baseUri, _toString(tokenId_))); /*:
      _toString(tokenId_)*/
  }
  // *******************
  // **************************************

  // **************************************
  // *****          INTERNAL          *****
  // **************************************
  // ***********
  // * IERC721 *
  // ***********
  /// @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
  /// The call is not executed if the target address is not a contract.
  ///
  /// @param from_ address owning the token being transferred
  /// @param to_ address the token is being transferred to
  /// @param tokenId_ identifier of the NFT being referenced
  /// @param data_ optional data to send along with the call
  ///
  /// @return isValidReceiver whether the call correctly returned the expected value
  function _checkOnERC721Received(
    address from_,
    address to_,
    uint256 tokenId_,
    bytes memory data_
  )
    internal
    virtual
    returns (bool isValidReceiver)
  {
    // This method relies on extcodesize, which returns 0 for contracts in
    // construction, since the code is only stored at the end of the
    // constructor execution.
    //
    // IMPORTANT
    // It is unsafe to assume that an address not flagged by this method
    // is an externally-owned account (EOA) and not a contract.
    //
    // Among others, the following types of addresses will not be flagged:
    //
    //  - 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
    uint256 _size_;
    assembly {
      _size_ := extcodesize(to_)
    }
    // If address is a contract, check that it is aware of how to handle ERC721 tokens
    if (_size_ > 0) {
      try IERC721Receiver(to_).onERC721Received(msg.sender, from_, tokenId_, data_) returns (bytes4 retval) {
        return retval == IERC721Receiver.onERC721Received.selector;
      } catch (bytes memory reason) {
        if (reason.length == 0) {
          revert IERC721_INVALID_RECEIVER();
        } else {
          assembly {
            revert(add(32, reason), mload(reason))
          }
        }
      }
    } else {
      return true;
    }
  }
  /// @dev Internal function returning whether a token exists.
  /// A token exists if it has been minted and is not owned by the zero address.
  ///
  /// @param tokenId_ identifier of the NFT being referenced
  ///
  /// @return tokenExist whether the token exists

  function _exists(uint256 tokenId_) internal view virtual returns (bool tokenExist) {
    if (tokenId_ == 0) {
      return false;
    }
    return tokenId_ < _nextId;
  }
  /// @dev Internal function returning whether `operator_` is allowed to handle `tokenId_`
  ///
  /// Note: To avoid multiple checks for the same data, it is assumed
  /// that existence of `tokenId_` has been verified prior via {_exists}
  /// If it hasn't been verified, this function might panic
  ///
  /// @param operator_ address that tries to handle the token
  /// @param tokenId_ identifier of the NFT being referenced
  ///
  /// @return isApproved whether `operator_` is allowed to manage the token

  function _isApprovedOrOwner(
    address tokenOwner_,
    address operator_,
    uint256 tokenId_
  )
    internal
    view
    virtual
    returns (bool isApproved)
  {
    return operator_ == tokenOwner_ || operator_ == getApproved(tokenId_) || _operatorApprovals[tokenOwner_][operator_];
  }
  /// @dev Mints `qty_` tokens and transfers them to `toAddress_`.
  ///
  /// Emits one or more {Transfer} event.
  ///
  /// @param toAddress_ address receiving the NFTs
  /// @param qty_ number of NFTs being minted

  function _mint(address toAddress_, uint256 qty_) internal virtual {
    uint256 _firstToken_ = _nextId;
    uint256 _nextStart_ = _firstToken_ + qty_;
    uint256 _lastToken_ = _nextStart_ - 1;
    _owners[_firstToken_] = toAddress_;
    if (_lastToken_ > _firstToken_) {
      _owners[_lastToken_] = toAddress_;
    }
    _nextId = _nextStart_;
    while (_firstToken_ < _nextStart_) {
      emit Transfer(address(0), toAddress_, _firstToken_);
      unchecked {
        ++_firstToken_;
      }
    }
  }
  /// @dev Mints `qty_` tokens and transfers them to `toAddress_`.
  ///
  /// Emits a {ConsecutiveTransfer} event.
  ///
  /// @param toAddress_ address receiving the NFTs
  /// @param qty_ number of NFTs being minted

  function _mint2309(address toAddress_, uint256 qty_) internal virtual {
    uint256 _firstToken_ = _nextId;
    uint256 _nextStart_ = _firstToken_ + qty_;
    uint256 _lastToken_ = _nextStart_ - 1;
    _owners[_firstToken_] = toAddress_;
    if (_lastToken_ > _firstToken_) {
      _owners[_lastToken_] = toAddress_;
    }
    _nextId = _nextStart_;
    emit ConsecutiveTransfer(_firstToken_, _lastToken_, address(0), toAddress_);
  }
  /// @dev Transfers `tokenId_` from `fromAddress_` to `toAddress_`.
  ///
  /// Emits a {Transfer} event.
  ///
  /// @param fromAddress_ the current owner of the NFT
  /// @param toAddress_ the new owner
  /// @param tokenId_ identifier of the NFT being referenced

  function _transfer(address fromAddress_, address toAddress_, uint256 tokenId_) internal virtual {
    _approvals[tokenId_] = address(0);
    uint256 _previousId_ = tokenId_ > 1 ? tokenId_ - 1 : 1;
    uint256 _nextId_ = tokenId_ + 1;
    bool _previousShouldUpdate_ =
      _previousId_ < tokenId_ && _exists(_previousId_) && _owners[_previousId_] == address(0);
    bool _nextShouldUpdate_ = _exists(_nextId_) && _owners[_nextId_] == address(0);
    if (_previousShouldUpdate_) {
      _owners[_previousId_] = fromAddress_;
    }
    if (_nextShouldUpdate_) {
      _owners[_nextId_] = fromAddress_;
    }
    _owners[tokenId_] = toAddress_;
    emit Transfer(fromAddress_, toAddress_, tokenId_);
  }
  // ***********

  // *******************
  // * IERC721Metadata *
  // *******************
  /// @notice Updates the baseUri for the tokens.
  ///
  /// @param newBaseUri_ the new baseUri for the tokens
  ///
  /// Requirements:
  ///
  /// - Caller must be the contract owner.
  function _setBaseUri(string memory newBaseUri_) internal virtual {
    _baseUri = newBaseUri_;
  }
  /// @dev Converts a `uint256` to its ASCII `string` decimal representation.
  ///
  /// @param value_ the value to convert to string.
  ///
  /// @return str the string representation of `value_`

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

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

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

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

File 11 of 16 : ERC173.sol
// SPDX-License-Identifier: MIT

/**
 * Author: Lambdalf the White
 */
pragma solidity ^0.8.17;

import { IERC173 } from "../interfaces/IERC173.sol";

abstract contract ERC173 is IERC173 {
  // **************************************
  // *****     STORAGE VARIABLES      *****
  // **************************************
  /// @dev The current contract owner.
  address private _owner;
  // **************************************

  constructor(address owner_) {
    _owner = owner_;
  }

  // **************************************
  // *****          MODIFIERS         *****
  // **************************************
  /// @dev Throws if called by any account other than the owner.
  modifier onlyOwner() {
    if (owner() != msg.sender) {
      revert IERC173_NOT_OWNER();
    }
    _;
  }
  // **************************************

  // **************************************
  // *****       CONTRACT_OWNER       *****
  // **************************************
  /// @dev Transfers ownership of the contract to `newOwner_`.
  ///
  /// @param newOwner_ address of the new contract owner
  ///
  /// Requirements:
  ///
  /// - Caller must be the contract owner.
  function transferOwnership(address newOwner_) public virtual override onlyOwner {
    address _oldOwner_ = _owner;
    _owner = newOwner_;
    emit OwnershipTransferred(_oldOwner_, newOwner_);
  }
  // **************************************

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

File 12 of 16 : ERC2981.sol
// SPDX-License-Identifier: MIT

/**
 * Author: Lambdalf the White
 */
pragma solidity ^0.8.17;

import { IERC2981 } from "../interfaces/IERC2981.sol";

abstract contract ERC2981 is IERC2981 {
  // **************************************
  // *****         DATA TYPES         *****
  // **************************************
  /// @dev A structure representing royalties
  struct RoyaltyData {
    address recipient;
    uint96 rate;
  }
  // **************************************

  // **************************************
  // *****    BYTECODE  VARIABLES     *****
  // **************************************
  /// @dev Royalty rate is stored out of 10,000 instead of a percentage
  ///   to allow for up to two digits below the unit such as 2.5% or 1.25%.
  uint256 public constant ROYALTY_BASE = 10_000;
  // **************************************

  // **************************************
  // *****     STORAGE VARIABLES      *****
  // **************************************
  /// @dev Represents the royalties on each sale on secondary markets.
  ///   Set rate to 0 to have no royalties.
  RoyaltyData private _royaltyData;
  // **************************************

  constructor(address royaltyRecipient_, uint96 royaltyRate_) {
    _setRoyaltyInfo(royaltyRecipient_, royaltyRate_);
  }

  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @dev Called with the sale price to determine how much royalty is owed and to whom.
  ///
  /// @param tokenId_ identifier of the NFT being referenced
  /// @param salePrice_ the sale price of the token sold
  ///
  /// @return receiver the address receiving the royalties
  /// @return royaltyAmount the royalty payment amount
  /* solhint-disable no-unused-vars */
  function royaltyInfo(
    uint256 tokenId_,
    uint256 salePrice_
  )
    public
    view
    virtual
    override
    returns (address receiver, uint256 royaltyAmount)
  {
    RoyaltyData memory _data_ = _royaltyData;
    if (salePrice_ == 0 || _data_.rate == 0 || _data_.recipient == address(0)) {
      return (address(0), 0);
    }
    uint256 _royaltyAmount_ = _data_.rate * salePrice_ / ROYALTY_BASE;
    return (_data_.recipient, _royaltyAmount_);
  }
  /* solhint-enable no-unused-vars */
  // **************************************

  // **************************************
  // *****          INTERNAL          *****
  // **************************************
  /// @dev Sets the royalty rate to `newRoyaltyRate_` and the royalty recipient to `newRoyaltyRecipient_`.
  ///
  /// @param newRoyaltyRecipient_ the address that will receive royalty payments
  /// @param newRoyaltyRate_ the percentage of the sale price that will be taken off as royalties,
  ///   expressed in Basis Points (100 BP = 1%)
  ///
  /// Requirements:
  ///
  /// - `newRoyaltyRate_` cannot be higher than {ROYALTY_BASE};
  function _setRoyaltyInfo(address newRoyaltyRecipient_, uint96 newRoyaltyRate_) internal virtual {
    if (newRoyaltyRate_ > ROYALTY_BASE) {
      revert IERC2981_INVALID_ROYALTIES();
    }
    _royaltyData = RoyaltyData(newRoyaltyRecipient_, newRoyaltyRate_);
  }
  // **************************************
}

File 13 of 16 : Whitelist.sol
// SPDX-License-Identifier: MIT

/**
 * Author: Lambdalf the White
 */
pragma solidity ^0.8.17;

import { IWhitelist } from "../interfaces/IWhitelist.sol";

abstract contract Whitelist is IWhitelist {
  // **************************************
  // *****     STORAGE VARIABLES      *****
  // **************************************
  /// @dev The address signing the whitelist proofs.
  address private _adminSigner;
  /// @dev Whitelist ID mapped to user's whitelist concumption.
  mapping(uint8 => mapping(address => uint256)) private _consumed;
  // **************************************

  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @dev Returns the amount that `account_` is allowed to access from the whitelist.
  ///
  /// @param account_ the address to validate access
  /// @param whitelistId_ the identifier of the whitelist being queried
  /// @param alloted_ the max amount of whitelist spots allocated
  /// @param proof_ the signature proof to validate whitelist allocation
  ///
  /// @return remainingAllocation the total amount of whitelist allocation remaining for `account_`
  ///
  /// Requirements:
  ///
  /// - `_adminSigner` must be set.
  function checkWhitelistAllowance(
    address account_,
    uint8 whitelistId_,
    uint256 alloted_,
    Proof memory proof_
  )
    public
    view
    virtual
    returns (uint256 remainingAllocation)
  {
    if (_adminSigner == address(0)) {
      revert WHITELIST_NOT_SET();
    }
    if (!_validateProof(account_, whitelistId_, alloted_, proof_)) {
      return 0;
    }
    return alloted_ - _consumed[whitelistId_][account_];
  }
  // **************************************

  // **************************************
  // *****          INTERNAL          *****
  // **************************************
  /// @dev Consumes `amount_` whitelist access passes from `account_`.
  ///
  /// Note: Before calling this function, eligibility should be checked through {checkWhitelistAllowance}.
  ///
  /// @param account_ the address to consume access from
  /// @param whitelistId_ the identifier of the whitelist being queried
  /// @param qty_ the amount of whitelist access consumed
  function _consumeWhitelist(address account_, uint8 whitelistId_, uint256 qty_) internal virtual {
    unchecked {
      _consumed[whitelistId_][account_] += qty_;
    }
  }
  /// @notice Updates the whitelist signer.
  ///
  /// @param newAdminSigner_ the new whitelist signer
  ///
  /// Requirements:

  function _setWhitelist(address newAdminSigner_) internal virtual {
    _adminSigner = newAdminSigner_;
  }
  /// @dev Internal function to decode a signature and compare it with the `_adminSigner`.
  ///
  /// @param account_ the address to validate access
  /// @param whitelistId_ the identifier of the whitelist being queried
  /// @param alloted_ the max amount of whitelist spots allocated
  /// @param proof_ the signature proof to validate whitelist allocation
  ///
  /// @return isValid whether the signature is valid or not

  function _validateProof(
    address account_,
    uint8 whitelistId_,
    uint256 alloted_,
    Proof memory proof_
  )
    internal
    view
    virtual
    returns (bool isValid)
  {
    bytes32 _digest_ = keccak256(abi.encode(block.chainid, whitelistId_, alloted_, account_));
    address _signer_ = ecrecover(_digest_, proof_.v, proof_.r, proof_.s);
    return _signer_ == _adminSigner;
  }
  // **************************************
}

File 14 of 16 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

/**
 * @dev Required interface of an ERC721 receiver compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-721[EIP].
 *   Note: the ERC-165 identifier for this interface is 0x150b7a02.
 */
interface IERC721Receiver {
  // **************************************
  // *****            VIEW            *****
  // **************************************
  /// @dev Handle the receipt of an NFT
  ///   The ERC721 smart contract calls this function on the recipient after a `transfer`.
  ///   This function MAY throw to revert and reject the transfer.
  ///   Return of other than the magic value MUST result in the transaction being reverted.
  ///   Note: the contract address is always the message sender.
  function onERC721Received(
    address operator_,
    address from_,
    uint256 tokenId_,
    bytes calldata data_
  )
    external
    returns (bytes4);
  // **************************************
}

File 15 of 16 : IERC2309.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

abstract contract IERC2309 {
  /// @dev Emitted instead of {ERC721.Transfer} when several consecutive tokens are being transferred.
  /// @dev See EIP2309 https://eips.ethereum.org/EIPS/eip-2309
  ///
  /// @param fromTokenId identifier of the first token being transferred
  /// @param toTokenId identifier of the last token being transferred
  /// @param fromAddress address tokens are being transferred from
  /// @param toAddress address tokens are being transferred to
  event ConsecutiveTransfer(
    uint256 indexed fromTokenId, uint256 toTokenId, address indexed fromAddress, address indexed toAddress
  );
}

File 16 of 16 : IWhitelist.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.4 <0.9.0;

interface IWhitelist {
  // **************************************
  // *****         DATA TYPES         *****
  // **************************************
  /// @dev A structure representing a signature proof to be decoded by the contract
  struct Proof {
    bytes32 r;
    bytes32 s;
    uint8 v;
  }
  // **************************************

  // **************************************
  // *****           ERRORS           *****
  // **************************************
  /// @dev Thrown when trying to query the whitelist while it's not set
  error WHITELIST_NOT_SET();
  /// @dev Thrown when operator does not have enough alloted access to fulfil their query
  error WHITELIST_FORBIDDEN();
  // **************************************
}

Settings
{
  "remappings": [
    "@lambdalf-dev/=node_modules/@lambdalf-dev/ethereum-contracts/src/",
    "forge-std/=node_modules/forge-std/src/",
    "ds-test/=node_modules/ds-test/src/",
    "solady/=node_modules/solady/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"reserve_","type":"uint256"},{"internalType":"uint96","name":"royaltyRate_","type":"uint96"},{"internalType":"address","name":"royaltyRecipient_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ARRAY_LENGTH_MISMATCH","type":"error"},{"inputs":[],"name":"CONTRACT_STATE_INCORRECT","type":"error"},{"inputs":[],"name":"CONTRACT_STATE_INVALID","type":"error"},{"inputs":[],"name":"ETHER_INCORRECT_PRICE","type":"error"},{"inputs":[],"name":"ETHER_NO_BALANCE","type":"error"},{"inputs":[],"name":"ETHER_TRANSFER_FAIL","type":"error"},{"inputs":[],"name":"IERC173_NOT_OWNER","type":"error"},{"inputs":[],"name":"IERC2981_INVALID_ROYALTIES","type":"error"},{"inputs":[],"name":"IERC721Enumerable_INDEX_OUT_OF_BOUNDS","type":"error"},{"inputs":[],"name":"IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS","type":"error"},{"inputs":[],"name":"IERC721_CALLER_NOT_APPROVED","type":"error"},{"inputs":[],"name":"IERC721_INVALID_APPROVAL","type":"error"},{"inputs":[],"name":"IERC721_INVALID_RECEIVER","type":"error"},{"inputs":[],"name":"IERC721_INVALID_TOKEN_OWNER","type":"error"},{"inputs":[],"name":"IERC721_NONEXISTANT_TOKEN","type":"error"},{"inputs":[],"name":"NFT_INVALID_QTY","type":"error"},{"inputs":[],"name":"NFT_INVALID_RESERVE","type":"error"},{"inputs":[],"name":"NFT_INVALID_SUPPLY","type":"error"},{"inputs":[],"name":"NFT_MAX_BATCH","type":"error"},{"inputs":[],"name":"NFT_MAX_RESERVE","type":"error"},{"inputs":[],"name":"NFT_MINTED_OUT","type":"error"},{"inputs":[],"name":"UNKNOWN","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"previousState","type":"uint8"},{"indexed":true,"internalType":"uint8","name":"newState","type":"uint8"}],"name":"ContractStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"ROYALTY_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts_","type":"address[]"},{"internalType":"uint256[]","name":"amounts_","type":"uint256[]"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"ownerBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"approved","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"internalType":"address","name":"operator_","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"isApproved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"tokenName","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"contractOwner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"tokenOwner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"salePrice_","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"approved_","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseUri_","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRoyaltyRecipient_","type":"address"},{"internalType":"uint96","name":"newRoyaltyRate_","type":"uint96"}],"name":"setRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId_","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"tokenSymbol","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"uri","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"supply","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner_","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405260015f55348015610013575f80fd5b506040516121e63803806121e683398101604081905261003291610164565b8082336040518060400160405280600a81526020016950657473204f6173697360b01b81525060405180604001604052806002815260200161504f60f01b81525081600590816100829190610253565b50600661008f8282610253565b5050600780546001600160a01b0319166001600160a01b039390931692909217909155506100bd82826100ef565b5050826009819055506100e760405180608001604052806059815260200161218d60599139610154565b50505061030d565b612710816001600160601b0316111561011b57604051635b75946560e11b815260040160405180910390fd5b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600855565b60046101608282610253565b5050565b5f805f60608486031215610176575f80fd5b835160208501519093506001600160601b0381168114610194575f80fd5b60408501519092506001600160a01b03811681146101b0575f80fd5b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806101e357607f821691505b60208210810361020157634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561024e57805f5260205f20601f840160051c8101602085101561022c5750805b601f840160051c820191505b8181101561024b575f8155600101610238565b50505b505050565b81516001600160401b0381111561026c5761026c6101bb565b6102808161027a84546101cf565b84610207565b6020601f8211600181146102b2575f831561029b5750848201515b5f19600385901b1c1916600184901b17845561024b565b5f84815260208120601f198516915b828110156102e157878501518255602094850194600190920191016102c1565b50848210156102fe57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b611e738061031a5f395ff3fe608060405234801561000f575f80fd5b506004361061018f575f3560e01c80636352211e116100dd578063a22cb46511610088578063cd3293de11610063578063cd3293de1461035e578063e985e9c514610367578063f2fde38b146103a2575f80fd5b8063a22cb46514610325578063b88d4fde14610338578063c87b56dd1461034b575f80fd5b80638da5cb5b116100b85780638da5cb5b146102f957806395d89b411461030a578063a0bcfc7f14610312575f80fd5b80636352211e146102c057806367243482146102d357806370a08231146102e6575f80fd5b806323b872dd1161013d57806342842e0e1161011857806342842e0e146102915780634f6ccce7146102a45780635f97036f146102b7575f80fd5b806323b872dd146102395780632a55205a1461024c5780632f745c591461027e575f80fd5b8063081812fc1161016d578063081812fc146101e5578063095ea7b31461021057806318160ddd14610223575f80fd5b806301ffc9a71461019357806302fa7c47146101bb57806306fdde03146101d0575b5f80fd5b6101a66101a136600461165d565b6103b5565b60405190151581526020015b60405180910390f35b6101ce6101c936600461169a565b61057d565b005b6101d86105de565b6040516101b2919061170d565b6101f86101f336600461171f565b61066e565b6040516001600160a01b0390911681526020016101b2565b6101ce61021e366004611736565b6106cf565b61022b610805565b6040519081526020016101b2565b6101ce61024736600461175e565b610819565b61025f61025a366004611798565b610902565b604080516001600160a01b0390931683526020830191909152016101b2565b61022b61028c366004611736565b6109c7565b6101ce61029f36600461175e565b610ac5565b61022b6102b236600461171f565b610ae4565b61022b61271081565b6101f86102ce36600461171f565b610b36565b6101ce6102e13660046118a3565b610be7565b61022b6102f4366004611966565b610d3b565b6007546001600160a01b03166101f8565b6101d8610df5565b6101ce6103203660046119d8565b610e04565b6101ce610333366004611a1d565b610e63565b6101ce610346366004611a4b565b610f2e565b6101d861035936600461171f565b610f7b565b61022b60095481565b6101a6610375366004611ac2565b6001600160a01b039182165f90815260026020908152604080832093909416825291909152205460ff1690565b6101ce6103b0366004611966565b610ff0565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061044757507fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d6300000000000000000000000000000000000000000000000000000000145b8061049357507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b806104df57507fffffffff0000000000000000000000000000000000000000000000000000000082167f7f5828d000000000000000000000000000000000000000000000000000000000145b8061052b57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b8061057757507fffffffff0000000000000000000000000000000000000000000000000000000082167f2a55205a00000000000000000000000000000000000000000000000000000000145b92915050565b336105906007546001600160a01b031690565b6001600160a01b0316146105d0576040517f4eec1aa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105da82826110ac565b5050565b6060600580546105ed90611af3565b80601f016020809104026020016040519081016040528092919081815260200182805461061990611af3565b80156106645780601f1061063b57610100808354040283529160200191610664565b820191905f5260205f20905b81548152906001019060200180831161064757829003601f168201915b5050505050905090565b5f8161067981611145565b6106af576040517f89a111e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f838152600160205260409020546001600160a01b031691505b50919050565b5f6106d982610b36565b9050806001600160a01b0316836001600160a01b031603610726576040517f47f5cd4600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0381165f8181526002602090815260408083203380855292529091205460ff16911480159061075a575080155b15610791576040517fbdc31d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8381526001602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0388811691821790925591518693918616917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b5f60015f546108149190611b6b565b905090565b6001600160a01b038216610859576040517f86292b6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61086382610b36565b9050806001600160a01b0316846001600160a01b0316146108b0576040517fa4b5692700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108bb81338461115b565b6108f1576040517fbdc31d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc8484846111cc565b50505050565b604080518082019091526008546001600160a01b03811682527401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1660208201525f908190831580610967575060208101516bffffffffffffffffffffffff16155b8061097a575080516001600160a01b0316155b1561098b575f8092509250506109c0565b5f6127108583602001516bffffffffffffffffffffffff166109ad9190611b7e565b6109b79190611b95565b91519350909150505b9250929050565b5f6001600160a01b038316610a08576040517fa4b5692700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6001815b5f54821015610a9357610a1f82611145565b15610a88575f828152600360205260409020546001600160a01b031615610a5a575f828152600360205260409020546001600160a01b031692505b826001600160a01b0316866001600160a01b031603610a8857808503610a84575091506105779050565b6001015b816001019150610a0d565b6040517f8adbcb8100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610adf83838360405180602001604052805f815250610f2e565b505050565b5f60015f54610af39190611b6b565b8210610b2b576040517fa8111f3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610577826001611bcd565b5f81610b4181611145565b610b77576040517f89a111e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f838152600360205260409020546001600160a01b03169150825b6001600160a01b038316610be0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015f818152600360205260409020546001600160a01b03169250610b92565b5050919050565b33610bfa6007546001600160a01b031690565b6001600160a01b031614610c3a576040517f4eec1aa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815181518114610c76576040517f88adebd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b82821015610cef57838281518110610c9357610c93611be0565b602002602001015181610ca69190611bcd565b9050610ce4858381518110610cbd57610cbd611be0565b6020026020010151858481518110610cd757610cd7611be0565b602002602001015161138c565b816001019150610c79565b600954811115610d2b576040517f6a52283100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805491909103905550505050565b5f6001600160a01b038216610d7c576040517fa4b5692700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60015b5f54811015610be057610d9281611145565b15610ded575f818152600360205260409020546001600160a01b031615610dcd575f818152600360205260409020546001600160a01b031691505b816001600160a01b0316846001600160a01b031603610ded578260010192505b600101610d80565b6060600680546105ed90611af3565b33610e176007546001600160a01b031690565b6001600160a01b031614610e57576040517f4eec1aa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e6081611485565b50565b336001600160a01b03831603610ea5576040517f47f5cd4600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f8181526002602090815260408083206001600160a01b0387168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610f39848484610819565b610f4584848484611491565b6108fc576040517f86292b6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081610f8781611145565b610fbd576040517f89a111e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004610fc8846115ed565b604051602001610fd9929190611c0d565b604051602081830303815290604052915050919050565b336110036007546001600160a01b031690565b6001600160a01b031614611043576040517f4eec1aa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b612710816bffffffffffffffffffffffff1611156110f6576040517fb6eb28ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526001600160a01b039092168083526bffffffffffffffffffffffff90911660209092018290527401000000000000000000000000000000000000000090910217600855565b5f815f0361115457505f919050565b505f541190565b5f836001600160a01b0316836001600160a01b0316148061119557506111808261066e565b6001600160a01b0316836001600160a01b0316145b806111c457506001600160a01b038085165f9081526002602090815260408083209387168352929052205460ff165b949350505050565b5f818152600160208190526040822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055821161120e576001611219565b611219600183611b6b565b90505f611227836001611bcd565b90505f838310801561123d575061123d83611145565b801561125d57505f838152600360205260409020546001600160a01b0316155b90505f61126983611145565b801561128957505f838152600360205260409020546001600160a01b0316155b905081156112d0575f84815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161790555b8015611315575f83815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161790555b5f8581526003602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a811691821790925591518893918b16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050505050565b5f80549061139a8383611bcd565b90505f6113a8600183611b6b565b5f84815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03881617905590508281111561142f575f81815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387161790555b5f8290555b8183101561147e5760405183906001600160a01b038716905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4826001019250611434565b5050505050565b60046105da8282611d12565b5f833b80156115e1576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0386169063150b7a02906114e59033908a9089908990600401611e0b565b6020604051808303815f875af192505050801561151f575060408051601f3d908101601f1916820190925261151c91810190611e4b565b60015b611594573d80801561154c576040519150601f19603f3d011682016040523d82523d5f602084013e611551565b606091505b5080515f0361158c576040517f86292b6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001491506111c49050565b50600195945050505050565b606060a06040510180604052602081039150505f815280825b600183039250600a81066030018353600a9004806116065750819003601f19909101908152919050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610e60575f80fd5b5f6020828403121561166d575f80fd5b813561167881611630565b9392505050565b80356001600160a01b0381168114611695575f80fd5b919050565b5f80604083850312156116ab575f80fd5b6116b48361167f565b915060208301356bffffffffffffffffffffffff811681146116d4575f80fd5b809150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61167860208301846116df565b5f6020828403121561172f575f80fd5b5035919050565b5f8060408385031215611747575f80fd5b6117508361167f565b946020939093013593505050565b5f805f60608486031215611770575f80fd5b6117798461167f565b92506117876020850161167f565b929592945050506040919091013590565b5f80604083850312156117a9575f80fd5b50508035926020909101359150565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561180e5761180e6117b8565b604052919050565b5f67ffffffffffffffff82111561182f5761182f6117b8565b5060051b60200190565b5f82601f830112611848575f80fd5b813561185b61185682611816565b6117e5565b8082825260208201915060208360051b86010192508583111561187c575f80fd5b602085015b83811015611899578035835260209283019201611881565b5095945050505050565b5f80604083850312156118b4575f80fd5b823567ffffffffffffffff8111156118ca575f80fd5b8301601f810185136118da575f80fd5b80356118e861185682611816565b8082825260208201915060208360051b850101925087831115611909575f80fd5b6020840193505b82841015611932576119218461167f565b825260209384019390910190611910565b9450505050602083013567ffffffffffffffff811115611950575f80fd5b61195c85828601611839565b9150509250929050565b5f60208284031215611976575f80fd5b6116788261167f565b5f8067ffffffffffffffff841115611999576119996117b8565b50601f8301601f19166020016119ae816117e5565b9150508281528383830111156119c2575f80fd5b828260208301375f602084830101529392505050565b5f602082840312156119e8575f80fd5b813567ffffffffffffffff8111156119fe575f80fd5b8201601f81018413611a0e575f80fd5b6111c48482356020840161197f565b5f8060408385031215611a2e575f80fd5b611a378361167f565b9150602083013580151581146116d4575f80fd5b5f805f8060808587031215611a5e575f80fd5b611a678561167f565b9350611a756020860161167f565b925060408501359150606085013567ffffffffffffffff811115611a97575f80fd5b8501601f81018713611aa7575f80fd5b611ab68782356020840161197f565b91505092959194509250565b5f8060408385031215611ad3575f80fd5b611adc8361167f565b9150611aea6020840161167f565b90509250929050565b600181811c90821680611b0757607f821691505b6020821081036106c9577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561057757610577611b3e565b808202811582820484141761057757610577611b3e565b5f82611bc8577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b8082018082111561057757610577611b3e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f808454611c1a81611af3565b600182168015611c315760018114611c6457611c91565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083168652811515820286019350611c91565b875f5260205f205f5b83811015611c8957815488820152600190910190602001611c6d565b505081860193505b50505083518060208601835e7f2e706e67000000000000000000000000000000000000000000000000000000009101908152600401949350505050565b601f821115610adf57805f5260205f20601f840160051c81016020851015611cf35750805b601f840160051c820191505b8181101561147e575f8155600101611cff565b815167ffffffffffffffff811115611d2c57611d2c6117b8565b611d4081611d3a8454611af3565b84611cce565b6020601f821160018114611d91575f8315611d5b5750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b17845561147e565b5f84815260208120601f198516915b82811015611dc05787850151825560209485019460019092019101611da0565b5084821015611dfc57868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f611e4160808301846116df565b9695505050505050565b5f60208284031215611e5b575f80fd5b81516116788161163056fea164736f6c634300081a000a68747470733a2f2f6261667962656965656e65666b6f7076706e743266767479356234676f3270796f71626b647370676e62666c673434726c71706232777561327a712e697066732e6e667473746f726167652e6c696e6b2f0000000000000000000000000000000000000000000000000000000000000c3700000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000aef33e18fc210a22dd42af5578837758b2349770

Deployed Bytecode

0x608060405234801561000f575f80fd5b506004361061018f575f3560e01c80636352211e116100dd578063a22cb46511610088578063cd3293de11610063578063cd3293de1461035e578063e985e9c514610367578063f2fde38b146103a2575f80fd5b8063a22cb46514610325578063b88d4fde14610338578063c87b56dd1461034b575f80fd5b80638da5cb5b116100b85780638da5cb5b146102f957806395d89b411461030a578063a0bcfc7f14610312575f80fd5b80636352211e146102c057806367243482146102d357806370a08231146102e6575f80fd5b806323b872dd1161013d57806342842e0e1161011857806342842e0e146102915780634f6ccce7146102a45780635f97036f146102b7575f80fd5b806323b872dd146102395780632a55205a1461024c5780632f745c591461027e575f80fd5b8063081812fc1161016d578063081812fc146101e5578063095ea7b31461021057806318160ddd14610223575f80fd5b806301ffc9a71461019357806302fa7c47146101bb57806306fdde03146101d0575b5f80fd5b6101a66101a136600461165d565b6103b5565b60405190151581526020015b60405180910390f35b6101ce6101c936600461169a565b61057d565b005b6101d86105de565b6040516101b2919061170d565b6101f86101f336600461171f565b61066e565b6040516001600160a01b0390911681526020016101b2565b6101ce61021e366004611736565b6106cf565b61022b610805565b6040519081526020016101b2565b6101ce61024736600461175e565b610819565b61025f61025a366004611798565b610902565b604080516001600160a01b0390931683526020830191909152016101b2565b61022b61028c366004611736565b6109c7565b6101ce61029f36600461175e565b610ac5565b61022b6102b236600461171f565b610ae4565b61022b61271081565b6101f86102ce36600461171f565b610b36565b6101ce6102e13660046118a3565b610be7565b61022b6102f4366004611966565b610d3b565b6007546001600160a01b03166101f8565b6101d8610df5565b6101ce6103203660046119d8565b610e04565b6101ce610333366004611a1d565b610e63565b6101ce610346366004611a4b565b610f2e565b6101d861035936600461171f565b610f7b565b61022b60095481565b6101a6610375366004611ac2565b6001600160a01b039182165f90815260026020908152604080832093909416825291909152205460ff1690565b6101ce6103b0366004611966565b610ff0565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061044757507fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d6300000000000000000000000000000000000000000000000000000000145b8061049357507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b806104df57507fffffffff0000000000000000000000000000000000000000000000000000000082167f7f5828d000000000000000000000000000000000000000000000000000000000145b8061052b57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b8061057757507fffffffff0000000000000000000000000000000000000000000000000000000082167f2a55205a00000000000000000000000000000000000000000000000000000000145b92915050565b336105906007546001600160a01b031690565b6001600160a01b0316146105d0576040517f4eec1aa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105da82826110ac565b5050565b6060600580546105ed90611af3565b80601f016020809104026020016040519081016040528092919081815260200182805461061990611af3565b80156106645780601f1061063b57610100808354040283529160200191610664565b820191905f5260205f20905b81548152906001019060200180831161064757829003601f168201915b5050505050905090565b5f8161067981611145565b6106af576040517f89a111e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f838152600160205260409020546001600160a01b031691505b50919050565b5f6106d982610b36565b9050806001600160a01b0316836001600160a01b031603610726576040517f47f5cd4600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0381165f8181526002602090815260408083203380855292529091205460ff16911480159061075a575080155b15610791576040517fbdc31d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8381526001602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0388811691821790925591518693918616917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b5f60015f546108149190611b6b565b905090565b6001600160a01b038216610859576040517f86292b6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61086382610b36565b9050806001600160a01b0316846001600160a01b0316146108b0576040517fa4b5692700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108bb81338461115b565b6108f1576040517fbdc31d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc8484846111cc565b50505050565b604080518082019091526008546001600160a01b03811682527401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1660208201525f908190831580610967575060208101516bffffffffffffffffffffffff16155b8061097a575080516001600160a01b0316155b1561098b575f8092509250506109c0565b5f6127108583602001516bffffffffffffffffffffffff166109ad9190611b7e565b6109b79190611b95565b91519350909150505b9250929050565b5f6001600160a01b038316610a08576040517fa4b5692700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6001815b5f54821015610a9357610a1f82611145565b15610a88575f828152600360205260409020546001600160a01b031615610a5a575f828152600360205260409020546001600160a01b031692505b826001600160a01b0316866001600160a01b031603610a8857808503610a84575091506105779050565b6001015b816001019150610a0d565b6040517f8adbcb8100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610adf83838360405180602001604052805f815250610f2e565b505050565b5f60015f54610af39190611b6b565b8210610b2b576040517fa8111f3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610577826001611bcd565b5f81610b4181611145565b610b77576040517f89a111e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f838152600360205260409020546001600160a01b03169150825b6001600160a01b038316610be0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015f818152600360205260409020546001600160a01b03169250610b92565b5050919050565b33610bfa6007546001600160a01b031690565b6001600160a01b031614610c3a576040517f4eec1aa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815181518114610c76576040517f88adebd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b82821015610cef57838281518110610c9357610c93611be0565b602002602001015181610ca69190611bcd565b9050610ce4858381518110610cbd57610cbd611be0565b6020026020010151858481518110610cd757610cd7611be0565b602002602001015161138c565b816001019150610c79565b600954811115610d2b576040517f6a52283100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805491909103905550505050565b5f6001600160a01b038216610d7c576040517fa4b5692700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60015b5f54811015610be057610d9281611145565b15610ded575f818152600360205260409020546001600160a01b031615610dcd575f818152600360205260409020546001600160a01b031691505b816001600160a01b0316846001600160a01b031603610ded578260010192505b600101610d80565b6060600680546105ed90611af3565b33610e176007546001600160a01b031690565b6001600160a01b031614610e57576040517f4eec1aa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e6081611485565b50565b336001600160a01b03831603610ea5576040517f47f5cd4600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f8181526002602090815260408083206001600160a01b0387168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610f39848484610819565b610f4584848484611491565b6108fc576040517f86292b6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081610f8781611145565b610fbd576040517f89a111e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004610fc8846115ed565b604051602001610fd9929190611c0d565b604051602081830303815290604052915050919050565b336110036007546001600160a01b031690565b6001600160a01b031614611043576040517f4eec1aa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b612710816bffffffffffffffffffffffff1611156110f6576040517fb6eb28ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526001600160a01b039092168083526bffffffffffffffffffffffff90911660209092018290527401000000000000000000000000000000000000000090910217600855565b5f815f0361115457505f919050565b505f541190565b5f836001600160a01b0316836001600160a01b0316148061119557506111808261066e565b6001600160a01b0316836001600160a01b0316145b806111c457506001600160a01b038085165f9081526002602090815260408083209387168352929052205460ff165b949350505050565b5f818152600160208190526040822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055821161120e576001611219565b611219600183611b6b565b90505f611227836001611bcd565b90505f838310801561123d575061123d83611145565b801561125d57505f838152600360205260409020546001600160a01b0316155b90505f61126983611145565b801561128957505f838152600360205260409020546001600160a01b0316155b905081156112d0575f84815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161790555b8015611315575f83815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161790555b5f8581526003602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a811691821790925591518893918b16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050505050565b5f80549061139a8383611bcd565b90505f6113a8600183611b6b565b5f84815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03881617905590508281111561142f575f81815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387161790555b5f8290555b8183101561147e5760405183906001600160a01b038716905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4826001019250611434565b5050505050565b60046105da8282611d12565b5f833b80156115e1576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0386169063150b7a02906114e59033908a9089908990600401611e0b565b6020604051808303815f875af192505050801561151f575060408051601f3d908101601f1916820190925261151c91810190611e4b565b60015b611594573d80801561154c576040519150601f19603f3d011682016040523d82523d5f602084013e611551565b606091505b5080515f0361158c576040517f86292b6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001491506111c49050565b50600195945050505050565b606060a06040510180604052602081039150505f815280825b600183039250600a81066030018353600a9004806116065750819003601f19909101908152919050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610e60575f80fd5b5f6020828403121561166d575f80fd5b813561167881611630565b9392505050565b80356001600160a01b0381168114611695575f80fd5b919050565b5f80604083850312156116ab575f80fd5b6116b48361167f565b915060208301356bffffffffffffffffffffffff811681146116d4575f80fd5b809150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61167860208301846116df565b5f6020828403121561172f575f80fd5b5035919050565b5f8060408385031215611747575f80fd5b6117508361167f565b946020939093013593505050565b5f805f60608486031215611770575f80fd5b6117798461167f565b92506117876020850161167f565b929592945050506040919091013590565b5f80604083850312156117a9575f80fd5b50508035926020909101359150565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561180e5761180e6117b8565b604052919050565b5f67ffffffffffffffff82111561182f5761182f6117b8565b5060051b60200190565b5f82601f830112611848575f80fd5b813561185b61185682611816565b6117e5565b8082825260208201915060208360051b86010192508583111561187c575f80fd5b602085015b83811015611899578035835260209283019201611881565b5095945050505050565b5f80604083850312156118b4575f80fd5b823567ffffffffffffffff8111156118ca575f80fd5b8301601f810185136118da575f80fd5b80356118e861185682611816565b8082825260208201915060208360051b850101925087831115611909575f80fd5b6020840193505b82841015611932576119218461167f565b825260209384019390910190611910565b9450505050602083013567ffffffffffffffff811115611950575f80fd5b61195c85828601611839565b9150509250929050565b5f60208284031215611976575f80fd5b6116788261167f565b5f8067ffffffffffffffff841115611999576119996117b8565b50601f8301601f19166020016119ae816117e5565b9150508281528383830111156119c2575f80fd5b828260208301375f602084830101529392505050565b5f602082840312156119e8575f80fd5b813567ffffffffffffffff8111156119fe575f80fd5b8201601f81018413611a0e575f80fd5b6111c48482356020840161197f565b5f8060408385031215611a2e575f80fd5b611a378361167f565b9150602083013580151581146116d4575f80fd5b5f805f8060808587031215611a5e575f80fd5b611a678561167f565b9350611a756020860161167f565b925060408501359150606085013567ffffffffffffffff811115611a97575f80fd5b8501601f81018713611aa7575f80fd5b611ab68782356020840161197f565b91505092959194509250565b5f8060408385031215611ad3575f80fd5b611adc8361167f565b9150611aea6020840161167f565b90509250929050565b600181811c90821680611b0757607f821691505b6020821081036106c9577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561057757610577611b3e565b808202811582820484141761057757610577611b3e565b5f82611bc8577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b8082018082111561057757610577611b3e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f808454611c1a81611af3565b600182168015611c315760018114611c6457611c91565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083168652811515820286019350611c91565b875f5260205f205f5b83811015611c8957815488820152600190910190602001611c6d565b505081860193505b50505083518060208601835e7f2e706e67000000000000000000000000000000000000000000000000000000009101908152600401949350505050565b601f821115610adf57805f5260205f20601f840160051c81016020851015611cf35750805b601f840160051c820191505b8181101561147e575f8155600101611cff565b815167ffffffffffffffff811115611d2c57611d2c6117b8565b611d4081611d3a8454611af3565b84611cce565b6020601f821160018114611d91575f8315611d5b5750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b17845561147e565b5f84815260208120601f198516915b82811015611dc05787850151825560209485019460019092019101611da0565b5084821015611dfc57868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f611e4160808301846116df565b9695505050505050565b5f60208284031215611e5b575f80fd5b81516116788161163056fea164736f6c634300081a000a

Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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