Cannot estimate gas; transaction may fail or may require manual gas limit

Hey everyone,

I am using Openzeppelin and Hardhat to build a Node.js server that can mint, transfer, and burn NFT’s. I am using Matic polygon testnet blockchain network to deploy my contracts

Here is my smart contract. (NFT.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyNFT is ERC721, Ownable {
    using Counters for Counters.Counter;
    using Strings for uint256;
    Counters.Counter private _tokenIds;
    mapping (uint256 => string) private _tokenURIs;
    string private _baseURIextended;

    constructor() ERC721("MyNFT", "MNFT") {}

    function _setTokenURI(uint256 tokenId, string memory _tokenURI)
        internal
        virtual
    {       
        _tokenURIs[tokenId] = _tokenURI;
    }

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

        string memory _tokenURI = _tokenURIs[tokenId];
        return _tokenURI;
    }

    function mint(address recipient, string memory uri)
        public
        returns (uint256)
    {
        _tokenIds.increment();

        uint256 newItemId = _tokenIds.current();
        _mint(recipient, newItemId);
        _setTokenURI(newItemId, uri);
        return newItemId;
    }

    function transfer(address _seller, address _buyer, uint256 _tokenId) external payable {
        // transfer assets from seller to buyer
        // seller pays the tx fees        
        setApprovalForAll(_seller, true);
        setApprovalForAll(_buyer, true);
        _transfer(_seller, _buyer, _tokenId);
    }

    function burn(uint256 _tokenId) public returns (bool) {
        _burn(_tokenId);
        return true;
    }
}

Here is my command to deploy the SC in blockchain.

const hre = require("hardhat");
async function main() {
  const NFT = await hre.ethers.getContractFactory("MyNFT");
  const nft = await NFT.deploy();
  await nft.deployed();
  console.log("NFT deployed to:", nft.address);
}
main().then(() => process.exit(0)).catch(error => {
  console.error(error);
  process.exit(1);
});

This script is working fine and giving me the contract address after I run this command.

npx hardhat run scripts/deploy-script.js --network matic   

Here is my Minting script.

const hre = require("hardhat");
async function main() {
  const NFT = await hre.ethers.getContractFactory("MyNFT");
  const URI = "ipfs://QmdnfzqwRuTmZwquauTxGs9hXzMaaVczmuSuQbpUU4pRng";
  const WALLET_ADDRESS = "my metamask wallet address -- its funded";
  const CONTRACT_ADDRESS = "contract address that I get from the command above";
  const contract = NFT.attach(CONTRACT_ADDRESS);
  const tokenId = await contract.mint(WALLET_ADDRESS, URI);
  console.log("NFT minted:", contract);
  console.log("TokenID:", tokenId);
}
main().then(() => process.exit(0)).catch(error => {
  console.error(error);
  process.exit(1);
});

This mints the token successfully and I get the response as well.

My problem arises when I am trying to transfer the NFT from one account to another or Burn the NFT.

Here is my transfer code.

const hre = require("hardhat");
async function main() {
  const NFT = await hre.ethers.getContractFactory("MyNFT");  
  const WALLET_ADDRESS = "my meta mask account address that owns NFT";
  const RECIEVER_ADDRESS = "the other meta mask account with 0 balance";
  const CONTRACT_ADDRESS = "the contract address I get";
  const TOKENID = "1";
  const contract = NFT.attach(CONTRACT_ADDRESS);
  await contract.transfer(WALLET_ADDRESS,RECIEVER_ADDRESS, TOKENID);
  console.log("NFT transferred:", contract);  
}
main().then(() => process.exit(0)).catch(error => {
  console.error(error);
  process.exit(1);
});

When i execute this script, i get this following error.

{ Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"ProviderError","code":-32000,"_isProviderError":true}, method="estimateGas", transaction={"from":"0xB705730CDdDb2Af877A92B8D21bee30A61C0a416","to":"0x6C1da88ACD16D6C3BCb0Fac3Fe2b4C7Aa95C68A0","data":"0x42966c680000000000000000000000003599fe1852aba39cf72d45f5b79f15fb0402eaed","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.2.0)
    at Logger.makeError (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/logger/src.ts/index.ts:213:28)
    at Logger.throwError (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/logger/src.ts/index.ts:225:20)
    at checkError (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:76:16)
    at EthersProviderWrapper.<anonymous> (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:512:20)
    at step (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:48:23)
    at Object.throw (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:29:53)
    at rejected (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:21:65)
    at process.internalTickCallback (internal/process/next_tick.js:77:7)
  reason:
   'cannot estimate gas; transaction may fail or may require manual gas limit',
  code: 'UNPREDICTABLE_GAS_LIMIT',
  error:
   ProviderError: execution reverted
    at HttpProvider.request (/home/shahidshaikh/projects/polygon-nfts/node_modules/hardhat/src/internal/core/providers/http.ts:46:19)
    at LocalAccountsProvider.request (/home/shahidshaikh/projects/polygon-nfts/node_modules/hardhat/src/internal/core/providers/accounts.ts:142:34)
    at process.internalTickCallback (internal/process/next_tick.js:77:7),
  method: 'estimateGas',
  transaction:
   { from: '0xB705730CDdDb2Af877A92B8D21bee30A61C0a416',
     to: '0x6C1da88ACD16D6C3BCb0Fac3Fe2b4C7Aa95C68A0',
     data:
      '0x42966c680000000000000000000000003599fe1852aba39cf72d45f5b79f15fb0402eaed',
     accessList: null } }

Same error when I am trying to burn the NFT using this command.

const hre = require("hardhat");
async function main() {
  const NFT = await hre.ethers.getContractFactory("MyNFT");    
  const CONTRACT_ADDRESS = "contract address";
  const TOKENID = "1";  
  const contract = NFT.attach(CONTRACT_ADDRESS);
  await contract.burn(TOKENID);
  console.log("NFT burned:", contract);  
}
main().then(() => process.exit(0)).catch(error => {
  console.error(error);
  process.exit(1);
});

Please let me know where I am doing a silly mistake!

2 Likes

@abcoathup Please have a look :slight_smile:

After adding this configuration parameters in hardhat configuration file, i am able to resolve this issue.

    matic: {
      url: "https://rpc-mumbai.maticvigil.com",
      accounts: [PRIVATE_KEY],
      gas: 2100000,
      gasPrice: 8000000000
    }
  },

However, now i am not able to successfully transfer the tokens to a different Matic account.

Here is my transfer code with contract address.

const hre = require("hardhat");
async function main() {
  const NFT = await hre.ethers.getContractFactory("MyNFT");  
  const WALLET_ADDRESS = "0xB705730CDdDb2Af877A92B8D21bee30A61C0a416";
  const RECIEVER_ADDRESS = "0xDF73E2c9D05bE9894E94dAD0BCc68FEBa4c2C7F9";
  const CONTRACT_ADDRESS = "0x6F0423B3F777C37E4613d20032173864734174d0";
  const TOKENID = "2";
  const contract = NFT.attach(CONTRACT_ADDRESS);
  const result = await contract.transfer(WALLET_ADDRESS,RECIEVER_ADDRESS, TOKENID);
  console.log("NFT transferred:", result);  
}
main().then(() => process.exit(0)).catch(error => {
  console.error(error);
  process.exit(1);
});

When i am running this i am getting this response.

NFT transferred: { hash:
   '0x62a85f7569096cef669fef461beecab1e4a34e1388c21574423ba2ef994c1f9b',
  type: 0,
  accessList: null,
  blockHash: null,
  blockNumber: null,
  transactionIndex: null,
  confirmations: 0,
  from: '0xB705730CDdDb2Af877A92B8D21bee30A61C0a416',
  gasPrice: BigNumber { _hex: '0x01dcd65000', _isBigNumber: true },
  gasLimit: BigNumber { _hex: '0x1127b8', _isBigNumber: true },
  to: '0x6F0423B3F777C37E4613d20032173864734174d0',
  value: BigNumber { _hex: '0x00', _isBigNumber: true },
  nonce: 36,
  data:
   '0xbeabacc8000000000000000000000000b705730cdddb2af877a92b8d21bee30a61c0a416000000000000000000000000df73e2c9d05be9894e94dad0bcc68feba4c2c7f90000000000000000000000000000000000000000000000000000000000000002',
  r:
   '0xbec8c54c7e4db82152cb85b2d14a4609d91b89dff51b9778c6656d41e6169833',
  s:
   '0x66ce4c0fee5d5763b882ea032365ffdfdf332647c41cfb877989fe0c7e175ace',
  v: 160037,
  creates: null,
  chainId: 80001,
  wait: [Function] }

When I view the transaction, i get this error in the explorer.

Error: (Awaiting internal transactions for reason)

Here is my Tx.

https://explorer-mumbai.maticvigil.com/tx/0x62a85f7569096cef669fef461beecab1e4a34e1388c21574423ba2ef994c1f9b/internal-transactions

Also, the to address is the contract address in the response. Shoud’nt it be the address I am passing?

1 Like

I am having the same issue although setting gas: 2100000, gasPrice: 8000000000 in the hardhat config did not solve my burn functionality. I have the same error as you and I am on the same polygon test network. Has anyone found a way to solve this issue?

2 Likes

The most likely reason for this error is that you are using "string" data type for URIs, and so the compiler naturally cannot estimate the gas usage when calling the mint function as the uri parameter's length can be arbitrary. Solidity documentation recommends the following:

As a general rule, use bytes for arbitrary-length raw byte data and string for arbitrary-length string (UTF-8) data. If you can limit the length to a certain number of bytes, always use one of the value types bytes1 to bytes32 because they are much cheaper.