Exception while processing transaction: out of gas

I have developed a smart contract and was able to deploy it to the testnet via Remix. However, I am unit testing using mocha and am running into an error.

This is an NFT contract using ERC721Enumerable and I set a reserve amount of 50 which mints 50 NFTS for the contract owner. With this set to 50 the unit tests work properly.

We wanted to increase the reserve from 50 to 200 and we get the following error in our unit test:

Error: Returned error: VM Exception while processing transaction: out of gas

:1234: Code to reproduce

The unit test code looks as follows

  it("should reserve the RESERVE_AMOUNT of tokens defined in contract", async () => {
    const { totalSupply, reserve, RESERVE_AMOUNT } = myContract.methods;
    await reserve().send();

    const reserveAmount = await RESERVE_AMOUNT().call();
    const currentSupply = await totalSupply().call();

    expect(currentSupply).to.equal(reserveAmount);
  });

:computer: Environment

My test environment config looks as follows:

module.exports = {
  accounts: {
    amount: 5,
    ether: 10,
  },
  contracts: {
    type: "web3",
    artifactsDir: "artifacts/contracts/MyContract.sol"
  }
}

Hi, since the OZ ERC721Enumerable doesnt include reserve, please post that code here.

@JulissaDantes here is the reserve function within the contract.

  function reserve() public onlyOwner {
    uint totalMinted = _tokenIds.current();

    require(totalMinted.add(RESERVE_AMOUNT) < MAX_SUPPLY, "Not enough tokens to reserve");

    for (uint i = 0; i < RESERVE_AMOUNT; i++) {
      _mintSingle();
    }
  }

My best guess is that is running out of gas inside the for loop, I dont know how big is RESERVE_AMOUNT at the moment of running the test, or if the _mintSingle might be messing with the RESERVE_AMOUNT amount making an infinite for loop.

So the testing works when RESERVE_AMOUNT = 50 but fails when RESERVE_AMOUNT = 200. The _mintSingle function looks like this

  function _mintSingle() private {
    uint newTokenID = _tokenIds.current();
    _safeMint(msg.sender, newTokenID);
    _tokenIds.increment();
  }

Are you saying this could be causing some sort of loop?

Now looking inside the _mintSingle, no I dont think thats whats happening. But seeing that it works at RESERVE_AMOUNT = 50 but not at RESERVE_AMOUNT = 200, is running out of gas inside the loop because is going to mint 200 new tokens and that is expensive, try sending 4 times what you send on the RESERVE_AMOUNT = 50 test to the RESERVE_AMOUNT = 200 test.

I assume you're talking about sending more gas. When in the test case i posted above if i send gas, like so:

    await reserve().send({
      from: owner,
      gas: 2000000000,
    });

I get the following error:

Error: Returned error: Exceeds block gas limit

If this helps, in the contract.options object i have these two properties for gas:

gas: 6000000,
gasPrice: '20000000000',