How to do two phases of mint and reserve some tokens for the owner of smart contract

Hello everyone, How i can reserve some tokens for the owner of smart contract.Ex: if the Max supply is 10000 and i want to reserve 100 there's any way to do that. And if i want to have two phases of the mint, first 5000 free mint and rest of 5000 cost 0.05ETH.

Also i changed this function and i'm not sure if that's correct.

modifier mintCompliance(uint256 _mintAmount) {
require(_mintAmount > 0 , 'Invalid mint amount!');
require(totalSupply() + _mintAmount <= maxSupply, 'Max supply exceeded!');
_;
}

This is the smart contract

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.9 <0.9.0;

import 'erc721a/contracts/extensions/ERC721AQueryable.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol';
import '@openzeppelin/contracts/security/ReentrancyGuard.sol';

contract OREDO is ERC721AQueryable, Ownable, ReentrancyGuard {

using Strings for uint256;

string public uriPrefix = '';
string public uriSuffix = '.json';

uint256 public cost;
uint256 public maxSupply;

bool public paused = true;
bool public revealed = true;

constructor(
string memory _tokenName,
string memory _tokenSymbol,
uint256 _cost,
uint256 _maxSupply
) ERC721A(_tokenName, _tokenSymbol) {
setCost(_cost);
maxSupply = _maxSupply;
}

modifier mintCompliance(uint256 _mintAmount) {
require(_mintAmount > 0 , 'Invalid mint amount!');
require(totalSupply() + _mintAmount <= maxSupply, 'Max supply exceeded!');
_;
}

modifier mintPriceCompliance(uint256 _mintAmount) {
require(msg.value >= cost * _mintAmount, 'Insufficient funds!');
_;
}

function mint(uint256 _mintAmount) public payable mintCompliance(_mintAmount) mintPriceCompliance(_mintAmount) {
require(!paused, 'The contract is paused!');

_safeMint(_msgSender(), _mintAmount);

}

function mintForAddress(uint256 _mintAmount, address _receiver) public mintCompliance(_mintAmount) onlyOwner {
_safeMint(_receiver, _mintAmount);
}

function _startTokenId() internal view virtual override returns (uint256) {
return 1;
}

function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
require(_exists(_tokenId), 'ERC721Metadata: URI query for nonexistent token');

string memory currentBaseURI = _baseURI();
return bytes(currentBaseURI).length > 0
    ? string(abi.encodePacked(currentBaseURI, _tokenId.toString(), uriSuffix))
    : '';

}

function setRevealed(bool _state) public onlyOwner {
revealed = _state;
}

function setCost(uint256 _cost) public onlyOwner {
cost = _cost;
}

function setUriPrefix(string memory _uriPrefix) public onlyOwner {
uriPrefix = _uriPrefix;
}

function setUriSuffix(string memory _uriSuffix) public onlyOwner {
uriSuffix = _uriSuffix;
}

function setPaused(bool _state) public onlyOwner {
paused = _state;
}

function withdraw() public onlyOwner nonReentrant {
// =============================================================================
(bool os, ) = payable(owner()).call{value: address(this).balance}('');
require(os);
// =============================================================================
}

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

You can do a team mint and call it to mint for free.
For sale states you can use separate booleans to configure that.

1 Like

Thank you for your support, can you help me do this because i'm still beginner for this.

hi, it depends...

here's one of many alternatives, to answer your first question: dev/team mint first, public mint later.

and this is just a very simple solution, create a state variable of boolean value:

bool public publicMintState;

u don't have to declare the value, since the default value is false.

create a setter function to modify the state of bool, like u did on setPaused.

create an error (revert) handling, on your public mint function:

require(!publicMintState, "Sale has not started yet.");

after contract is deployed, dev/team mintForAddress start first until reach 100 total supply (or whatever amounts u desire), switch the publicMintState to true before public start to mint.

hope it helps.

1 Like

Hi,
Yeah you can do.

For the first question, you can always write the public function to check whether the mint amount is less greater than the max amount minus the amount you want to save, as in :

require(totalSupply() + _mintAmount <= (maxSupply - ownerAmount), "Max Supply reached");

The ownerAmount is the amount you want to reserve for yourself.

Then you can make a function for yourself to mint using the onlyOwner modifier. You can always write a require statement to make sure you don't exceed your limit.

To your second answer, for that, you need to create two mint functions, one for the freemint, the other for the paidmint.
You can use the require statement to hit the limits you want, ex: 5000 for free and the rest for paid as you said.

The modifier looks fine to me.

Apart from that, you can also write flags to trigger the free and paid mints respectively to make sure one comes after the other.

2 Likes

Thank you for you support. I try to set the free mint phase "maxFreeMint" and it's working but the "maxMintAmountPerWallet" function it's not working. Can you help me with this and please provide me code because i try lot of solution and is not working.

pragma solidity >=0.8.9 <0.9.0;

import 'erc721a/contracts/extensions/ERC721AQueryable.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol';
import '@openzeppelin/contracts/security/ReentrancyGuard.sol';

contract DD is ERC721AQueryable, Ownable, ReentrancyGuard {

  using Strings for uint256;

  string public baseURI = '';
  string public uriSuffix = '.json';
  
  uint256 public cost;
  uint256 public maxSupply;
  uint256 public maxFreeMint = 4;
  uint256 public maxMintAmountPerWallet = 2;

  mapping(address => uint256) private _freeWalletMints;

  bool public paused = true;

  constructor(
    string memory _tokenName,
    string memory _tokenSymbol,
    uint256 _cost,
    uint256 _maxSupply
  ) ERC721A(_tokenName, _tokenSymbol) {
    setCost(_cost);
    maxSupply = _maxSupply;
  }

  modifier mintCompliance(uint256 _mintAmount) {

    require(_mintAmount > 0, 'Invalid mint amount!');
    require(totalSupply() + _mintAmount <= maxSupply, 'Max supply exceeded!');

    _;
  }


  function mint(uint256 _mintAmount) public payable mintCompliance(_mintAmount){
    if(msg.sender != owner()){
      require(!paused, 'The contract is paused!');
      require(_freeWalletMints[_msgSender()] + _mintAmount <= 2, 'You have already minted');
      if (totalSupply()+_mintAmount > maxFreeMint){
          require(msg.value >= cost * _mintAmount, "Insufficient funds!");
        }
      }
      _safeMint(_msgSender(), _mintAmount);
    }

  function _startTokenId() internal view virtual override returns (uint256) {
    return 1;
  }

  function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
    require(_exists(_tokenId), 'ERC721Metadata: URI query for nonexistent token');

    string memory currentBaseURI = _baseURI();
    return bytes(currentBaseURI).length > 0
        ? string(abi.encodePacked(currentBaseURI, _tokenId.toString(), uriSuffix))
        : '';
  }

  function setCost(uint256 _cost) public onlyOwner {
    cost = _cost;
  }
  function setBaseURI(string memory _url) public onlyOwner {
    baseURI = _url;
  }

  function setUriSuffix(string memory _uriSuffix) public onlyOwner {
    uriSuffix = _uriSuffix;
  }

  function setPaused(bool _state) public onlyOwner {
    paused = _state;
  }

  function withdraw() public onlyOwner nonReentrant {
    (bool os, ) = payable(owner()).call{value: address(this).balance}('');
    require(os);
  }

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

I'm confused, you haven't used that function anywhere.

Forget about the reserve tokens, I just need to set fix free supply with maxFreeMint and limit the mint per wallet on this free mint phase to be 2 tokens per wallet using mapping mapping(address => uint256) private _freeWalletMints; and maxMintAmountPerWallet
if you can provide me your code to do this and thank you in advance.