Static Fee Mint

If the auction style mint from the original sample doesn't meet your needs and you'd rather have a static value for your mint price you can use this SampleNFT contract in place of the final SampleNFT contract on the main page. The key things to note here are that with this version of the contract the collection owner needs to send in a togglePublicMint() and toggleWhitelistMint() transactions to start those sales. There are ways to further alter the contract so those can be set times in the future rather than owner toggles if you need that functionality.

contract SampleNFT is Ownable, ERC721A, ReentrancyGuard {
  uint256 public immutable maxPerAddressDuringMint;
  uint256 public immutable amountForDevs;
  uint256 public immutable amountForAuctionAndDev;

  uint256 public publicMintPrice;
  uint256 public whitelistMintPrice;
  
  bool public publicSaleActive;
  bool public whitelistMintActive;

  mapping(address => uint256) public allowlist;

  constructor(
    uint256 maxBatchSize_,
    uint256 collectionSize_,
    uint256 amountForAuctionAndDev_,
    uint256 amountForDevs_,
    uint256 whitelistPrice_,
    uint256 publicPrice_
  ) ERC721A("Sample NFT", "SMPNFT", maxBatchSize_, collectionSize_) {
    maxPerAddressDuringMint = maxBatchSize_;
    amountForAuctionAndDev = amountForAuctionAndDev_;
    amountForDevs = amountForDevs_;
    whitelistMintPrice = whitelistPrice_;
    publicMintPrice = publicPrice_;
    require(
      amountForAuctionAndDev_ <= collectionSize_,
      "larger collection size needed"
    );
  }

  modifier callerIsUser() {
    require(tx.origin == msg.sender, "The caller is another contract");
    _;
  }

  function allowlistMint() external payable callerIsUser {
    uint256 price = whitelistMintPrice;
    require(whitelistMintActive, "allowlist sale has not begun yet");
    require(allowlist[msg.sender] > 0, "not eligible for allowlist mint");
    require(totalSupply() + 1 <= collectionSize, "reached max supply");
    allowlist[msg.sender]--;
    _safeMint(msg.sender, 1);
    refundIfOver(price);
  }

  function publicSaleMint(uint256 quantity)
    external
    payable
    callerIsUser
  {
    require(publicSaleActive,"public sale has not begun yet");
    require(totalSupply() + quantity <= collectionSize, "reached max supply");
    require(
      numberMinted(msg.sender) + quantity <= maxPerAddressDuringMint,
      "can not mint this many"
    );
    _safeMint(msg.sender, quantity);
    refundIfOver(publicMintPrice * quantity);
  }

  function refundIfOver(uint256 price) private {
    require(msg.value >= price, "Need to send more ETH.");
    if (msg.value > price) {
      payable(msg.sender).transfer(msg.value - price);
    }
  }

  function togglePublicMint() external onlyOwner{
      publicSaleActive = !publicSaleActive;
  }

  function toggleWhitelistMint() external onlyOwner{
      publicSaleActive = !publicSaleActive;
  }
  
  function setPublicMintPrice(uint256 _cost) external onlyOwner{
      publicMintPrice = _cost;
  }
  
  function setWhitelistMintPrice(uint256 _cost) external onlyOwner{
      whitelistMintPrice = _cost;
  }

  function seedAllowlist(address[] memory addresses, uint256[] memory numSlots)
    external
    onlyOwner
  {
    require(
      addresses.length == numSlots.length,
      "addresses does not match numSlots length"
    );
    for (uint256 i = 0; i < addresses.length; i++) {
      allowlist[addresses[i]] = numSlots[i];
    }
  }

  // For marketing etc.
  function devMint(uint256 quantity) external onlyOwner {
    require(
      totalSupply() + quantity <= amountForDevs,
      "too many already minted before dev mint"
    );
    require(
      quantity % maxBatchSize == 0,
      "can only mint a multiple of the maxBatchSize"
    );
    uint256 numChunks = quantity / maxBatchSize;
    for (uint256 i = 0; i < numChunks; i++) {
      _safeMint(msg.sender, maxBatchSize);
    }
  }

  // // metadata URI
  string private _baseTokenURI;

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

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

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

  function setOwnersExplicit(uint256 quantity) external onlyOwner nonReentrant {
    _setOwnersExplicit(quantity);
  }

  function numberMinted(address owner) public view returns (uint256) {
    return _numberMinted(owner);
  }

  function getOwnershipData(uint256 tokenId)
    external
    view
    returns (TokenOwnership memory)
  {
    return ownershipOf(tokenId);
  }
}

Last updated