0

when I call a contract method, which should revert and throw error:

Contract souce code:

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract VeryGoodNftWithMaxSupply is ERC721URIStorage {

  uint256 private _currentId = 0;
  address public rootAddress = address(0);
  uint256 public _maxSupply = 3;

  event Minted(address to, uint256 nftId, address minter);

  modifier shouldLessThanMaxSupply(){
    require(
      _currentId < _maxSupply, "Reached max supply, no available nft left"
    );
    // 下划线表示被hook方法的内容。 会在编译、执行的时候做个替换
    _;
  }

  constructor() ERC721("VeryGoodNftWithMaxSupply", "VGNWM") {
    rootAddress = msg.sender;
  }

  function mint(address to) external shouldLessThanMaxSupply{
    uint256 nftId = _currentId + 1;
    _mint(to, nftId);
    _currentId = nftId;
    address from = msg.sender;
    emit Minted(to, nftId, from);
  }
}

and the script calling this contract (callVeryGoodNftWithMaxSupply.js ) looks like:

const CONTRACT_ADDRESS = "0x7eB6D07B6A69a2Be809dAed88d456C1460aA7C3e"
const contractJson = require('./build/contracts/VeryGoodNftWithMaxSupply.json')

module.exports = async function (callback) {
  const contract = new web3.eth.Contract( contractJson.abi, CONTRACT_ADDRESS );

  const network = await web3.eth.net.getNetworkType()

  // This method will meet the error ( rever : max nft supply reached ... ) 
  const tx = contract.methods.mint('0xc0dD5021e298dB57bEF361C735cd1C04cef2E48A')

  const receipt = await tx
  .send({
    from: (await web3.eth.getAccounts())[0], 
    gas: await tx.estimateGas(),
  })
  .once('sending', (payload) => {
    console.info("-- in sending..., payload: ", payload)
  })
  .once('sent', (payload) => {
    console.info("-- in sent..., payload: ", payload)
  })
  .once("transactionHash" , (txHash) => {
    console.log(`Mining transaction ... network: ${network}, tx: ${txhash}`)
    // console.log(`https://${network}.etherscan.io/tx/${txhash}`)
  })
  .once('receipt', (receipt) => {
    console.info("-- in receipt...", receipt)
    console.log('====== total: ')
    console.log(receipt)
    console.log('====== events.Minted: ', receipt.events.Minted)
    // Success, you've minted the NFT. The transaction is now on chain!
    console.log(
        `Success: The NFT has been minted and mined in block ${receipt.blockNumber}`)
    callback()
  })
  .on('confirmation', (confNumber, receipt, lastBlockHash) => {
    console.info("-- in confirm...", receipt)
  })
  .on('error', (error) => {
    console.error(`An error happened: ${error}`)
    callback()
  })

}

However, when I typed the command and press enter, it just stuck , no error , and the program is always running,

and when I press ctrl + c , error message is shown:

 ^CUnhandledRejections detected
Promise {
  <rejected> Error: VM Exception while processing transaction: revert Reached max supply, no available nft left
  {
    "stack": "RuntimeError: VM Exception while processing transaction: revert Reached max supply, no available nft left\n    at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n    at module.exports (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\gas\\guestimation.js:142:32)",
    "name": "RuntimeError"
  }
....

What could I do to make it throw error ,but not stuck ?

1 Answer 1

0

I got the answer: if the contract call has potential problem, it will throw error when we estimate the gas.

  const receipt = await tx
  .send({
    from: (await web3.eth.getAccounts())[0], 
    gas: await tx.estimateGas(),   // <---  in this step, the error occurs
  })

I found this clue when call the contract using remix + metamask, I found this:

enter image description here

so the solution is quite simple: just catch this error when you estimateGas, the improved code looks like:

  console.info("== before estimateGas: ")
  let gas = await tx.estimateGas()
  .then(function(e){
    console.log(e)
  }).catch(function(e){
    throw("got error, lets stop:", e)
    console.log(e)
  })
  console.info("== after estimateGas: ", gas)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.