ETH Price: $3,336.81 (-0.36%)
 

Overview

Max Total Supply

2,850 PO

Holders

419

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
4 PO
0x49f9036437e6e2c68433e49c36aa8ba0f86b4ce0
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
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

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

0000000000000000000000000000000000000000000000000000000000000c3700000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000aef33e18fc210a22dd42af5578837758b2349770

-----Decoded View---------------
Arg [0] : reserve_ (uint256): 3127
Arg [1] : royaltyRate_ (uint96): 500
Arg [2] : royaltyRecipient_ (address): 0xaeF33e18FC210a22dD42AF5578837758B2349770

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000c37
Arg [1] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [2] : 000000000000000000000000aef33e18fc210a22dd42af5578837758b2349770


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.