(ERC721) Is my mint() function guaranteed to mint consecutive tokenIDs for each user who calls it?

Dear all,

It is great to see such a thriving community here. I hope my question (as a beginner blockchain dev) is not too basic.

I have the following mint() function that uses OpenZeppelin's _safemint() in my ERC721 contract:

  function mint(uint256 _mintAmount) public payable {
    uint256 supply = totalSupply();
    require(!paused);
    require(_mintAmount > 0);
    require(_mintAmount <= maxMintAmount);
    require(_mintAmount%4==0);
    require(supply + _mintAmount <= maxSupply);

    if (msg.sender != owner()) {
      require(msg.value >= cost * _mintAmount);
    }

    for (uint256 i = 1; i <= _mintAmount; i++) {
      _safeMint(msg.sender, supply + i);
        isRevealed.push(false);
    }
  }

The specific collection that I am building requires that:

  • users mint in multiples of 4 or doesn't mint any NFTs at all

  • each user who calls (transacts with) the mint function above gets consecutive tokenIDs - e.g. 1,2,3,4 or 5,6,7,8.

A user should never:

  • get non-consecutive tokenIDs, e.g. 1,2,3,5

  • mint some number other than 0 and a multiple of 4, for example - 2 NFTs - tokenIDs 1 and 2, for example

  • Mint four consecutive tokenIDs with a beginning tokenID that is not 1, 5, 9, 13, etc. - e.g. tokenIDs 3,4,5 6. This would happen if for example someone before that only minted tokenIDs 1 and 2.

As far as I understand Ethereum transactions are atomic - either the whole transaction executes or none of it. So because of my "require(_mintAmount%4==0)" I am guessing that users will always be minting in multiples of 4 or 0 NFTs (please, correct me if I am wrong). However, I am concerned that:

  • the mint() function could be executing concurrently for many users and mint 4 non-consecutive tokenIDs for each user; on one hand I read that the EVM is single-threaded, so only one person could be in mint() at a time, on the other hand - don't reentrancy attacks exist exactly because it is possible to enter a function before it has stopped executing a previous call to it? I must be missing something (again, I am a beginner)

  • there is another way that I am unaware of (an "unknown unknown" kind of problem) that the function will exhibit one of the unwanted behaviors listed above, for example mint only two tokenIDs during some call - then this will not only be an issue for this user, but for all users, and the whole project will be ruined. The project depends on every user getting exactly 4 consecutive IDs, exactly from tokenID 1.

Do you think this function will satisfy the behavior that I am looking for? If not, can you think of possible fixes? Thank you all!