Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UNPREDICTABLE_GAS_LIMIT #2248

Closed
HakunamatataLeo opened this issue Jan 12, 2022 · 37 comments
Closed

UNPREDICTABLE_GAS_LIMIT #2248

HakunamatataLeo opened this issue Jan 12, 2022 · 37 comments
Assignees
Labels
type:bug Something isn't working

Comments

@HakunamatataLeo
Copy link

Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"ProviderError","code":-32000,"_isProviderError":true,"data":"null"}, method="call", transaction={"from":“0x3c82D4291cF4bAeADb7e5E05f5cB0c0xxxxxxxx","to":"0x3c82D4291cF4bAeADb7e5E05f5cB0xxxxxxxxx","data":"0x6352211e0000000000000000000000000000000000000000000000000000000000000001","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.5.1)

@feuGeneA
Copy link
Contributor

While it's good for us to know when such errors are happening in the wild, there's little we can do about it with just an error message.

Can you provide more information? Specifically, it would be ideal if you could provide your hardhat project (including all relevant files and folders). At the very least, we would need some instructions on how to reproduce the problem you are seeing.

@feuGeneA feuGeneA added the status:needs-more-info There's not enough information to start working on this issue label Jan 12, 2022
@HakunamatataLeo
Copy link
Author

HakunamatataLeo commented Jan 13, 2022

my contract content:

    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

my handhat.config.js content:

require("@nomiclabs/hardhat-waffle");
require("./tasks/deployGreeter");
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
  const accounts = await hre.ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: "0.8.7",
  networks: {
    hardhat: {
      allowUnlimitedContractSize: true,
    },
    mychain: {
      url: 'http://172.23.23.23:8600',
      gasPrice: 1500000000,
      chainId: 67,
      gas: 4100000,
      accounts: [
        '0x37ffa6xxxxx1',
        '0x37ffa6xxxxx2',
        '0x37ffa6xxxxx3',
        '0x37ffa6xxxxx4'
      ],
    },
  },
};

my test.js content:

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("C001 contract Test", function () {
  let owner;
  let addr1;
  let addr2;
  let addr3;
  let AdminAuth;
  let AdminContractAddr;
  let DelegateAuth;
  let DelegateContractAddr; 
  let C001Auth;
  let C001Token;
  let bcauth;
  beforeEach(async function(){
    // deploy AdminAuth
    AdminAuth = await ethers.getContractFactory("AdminAuth");
    [owner, addr1, addr2, addr3] = await ethers.getSigners(); 
    AdminToken = await AdminAuth.deploy([owner.address], { gasLimit: 4100000 });
    // get AdminContractAddr
    AdminContractAddr = AdminToken["deployTransaction"]["creates"] 
    
    // deploy DelegateAuth
    DelegateAuth = await ethers.getContractFactory("DelegateAuth");
    DelegateToken = await DelegateAuth.deploy([addr1.address], { gasLimit: 4100000 }); 
    // get DelegateContractAddr
    DelegateContractAddr = DelegateToken["deployTransaction"]["creates"]

    // deploy C001
    C001Auth = await ethers.getContractFactory("C001")
    C001Token = await C001Auth.deploy('BC001','bc001',AdminContractAddr,[DelegateContractAddr],"")
  
  });
  describe("Deployment && Test", function(){
    it("mint BC001", async function () {
      console.log("C001_ContractsAddr:",C001Token["deployTransaction"]["creates"])
      console.log("C001_Deploy_tx_hash:",C001Token["deployTransaction"]["hash"])
      let cauth = C001Token
      let ret = await bcauth.mint(addr1.address,1,"tk001")
      console.log(bcauth["deployTransaction"]["creates"])
      console.log("mint_tx_hash:", ret["hash"])
      let rets = await bcauth.ownerOf(1) // this step error out,above upon all is success
      console.log(rets)
      
  });

@HakunamatataLeo
Copy link
Author

cmd:
npx hardhat test --network mychain

@feuGeneA

@feuGeneA
Copy link
Contributor

@HakunamatataLeo That's progress, but we're still not at a reproduction scenario yet. This gives us some more hints, but without complete copies of the contracts used in your test, we cannot possibly reproduce the issue, and without reproducing an issue we cannot fix it.

@feuGeneA
Copy link
Contributor

@ErrorEater
Copy link

ErrorEater commented Jan 26, 2022

I'm having the same error but not while deploying on forked Mainnet but while deploying on Ropsten network!
If I manually execute the command on Remix it works.

Edit: Solved the issue by adding gas: 6000000 field to my config file.

    eth_ropsten: {
      url: eth_ropsten.url,
      chainId: 3,
      gasPrice: 20000000000,
      gas: 6000000,
      accounts: { mnemonic: eth_ropsten.mnemonic }
    }

@toshiSat
Copy link

This is happening to me while deploying to the goerli network, adding gas doesn't fix it for me

@feuGeneA
Copy link
Contributor

@toshiSat can you provide a reproduction scenario?

@toshiSat
Copy link

toshiSat commented Feb 17, 2022

I figured my issue out. It didn't like approve infinite in the constructor. Once I put those in an initialize functions, the deployments worked

@fvictorio
Copy link
Member

Closing this for lack of reproduction steps.

@nedgar
Copy link

nedgar commented Mar 7, 2022

I'm seeing this with @nomiclabs/hardhat-ethers and ethers 5.5.4.

To reproduce, call ownerOf(id) public view on any ERC-721 contract where the token does not exist.
The contract typically rejects with a message like: ERC721: owner query for nonexistent token, which the client receives as a ProviderError with message: execution reverted: ERC721: owner query for nonexistent token. The ethers library's JsonRpcProvider converts the method to Error: cannot estimate gas; transaction may fail or may require manual gas limit when the method is estimateGas or call.
See https://github.com/ethers-io/ethers.js/blob/master/packages/providers/src.ts/json-rpc-provider.ts#L79

I'll log this to an open discussion item for ethers: ethers-io/ethers.js#2602

@nedgar
Copy link

nedgar commented Mar 8, 2022

I've added a standalone example there.

It seems to be a combination of factors. Something with the hardhat config changes the original error message to have execution reverted: (plus the error message from the contract), which then matches the case in JsonRpcProvider.checkErrors.

@fvictorio
Copy link
Member

Thanks for the detailed info @nedgar. So this looks like an ethers.js thing? If not and if you think there's something we can do on our side, please let us know.

@nedgar
Copy link

nedgar commented Mar 8, 2022

Hi @fvictorio. It's actually a combination of both HardHat and ethers.js.
See TL;DR here: ethers-io/ethers.js#2602 (reply in thread).

I've been unable to reproduce it using ethers.js on its own. But it's code in ethers.js's JsonRpcProvider that incorrectly converts the error raised by the contract in the case of a missing token (e.g. "ERC721: owner query for nonexistent token") from an error with:
code: "CALL_EXCEPTION", reason: "ERC721: owner query for nonexistent token"
to one with:
code: "UNPREDICTABLE_GAS_LIMIT", reason: "cannot estimate gas; transaction may fail or may require manual gas limit"
even when the gasLimit is given explicitly. It actually executes the call OK, but the problem is in the error handling.

Here is a standalone example (simplified further from the one here: ethers-io/ethers.js#2602 (comment)).
It fails when run with HardHat (with usual mainnet config), but works OK when the plain ethers JsonRpcProvider is used (even when still run under HardHat, i.e. using its injected ethers).

// const { ethers } = require("ethers");
const {
  CONTRACT_ADDRESS = "0x198478f870d97d62d640368d111b979d7ca3c38f", // https://opensea.io/collection/8sian-main-collection (on Ethereum)
  INFURA_KEY,
  PRIVATE_KEY
} = process.env;

const ABI = [
  "function ownerOf(uint256 id) view returns (address)",
];

async function main() {
  // use HardHat config
  const [signer] = await ethers.getSigners();
  const { provider } = signer;

  // use plain Ethers.js
  // const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/" + INFURA_KEY);
  // const signer = new ethers.Wallet(PRIVATE_KEY, provider);

   // works with plain Ethers.js, but fails with "cannot estimate gas"... with HardHat
  const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider /* or signer */);

  // expectation:
  // id 0 should throw an error with code CALL_EXCEPTION and reason "ERC721: owner query for nonexistent token",
  // ids 1 to 8888 should return its owner's address
  const id = 0;
  const owner = await contract.ownerOf(id, { gasLimit: 100000 }); // giving gasLimit makes no difference
  console.log("Owner is:", owner);
}

main()
  .then(() => {
    console.log("Completed normally.");
    process.exit();
  })
  .catch((err) => {
    console.log("Error!", err);
    process.exit(1);
  });

When run using hardhat, it fails with the UNPREDICTABLE_GAS_LIMIT

$ npx hardhat run --no-compile scripts/test-owner-of-simple.js --network mainnet
Error! Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"ProviderError","code":3,"_isProviderError":true,"data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000294552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000000000"}, method="call", transaction={"gasLimit":{"type":"BigNumber","hex":"0x0186a0"},"to":"0x198478F870d97D62D640368D111b979d7CA3c38F","data":"0x6352211e0000000000000000000000000000000000000000000000000000000000000000","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.5.3)
    at Logger.makeError (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/logger/src.ts/index.ts:225:28)
    at Logger.throwError (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/logger/src.ts/index.ts:237:20)
    at checkError (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:80:16)
    at EthersProviderWrapper.<anonymous> (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:562:20)
    at step (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:48:23)
    at Object.throw (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:29:53)
    at rejected (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:21:65)
    at processTicksAndRejections (internal/process/task_queues.js:95:5) {
  reason: 'cannot estimate gas; transaction may fail or may require manual gas limit',
  code: 'UNPREDICTABLE_GAS_LIMIT',
  error: ProviderError: execution reverted: ERC721: owner query for nonexistent token
      at HttpProvider.request (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/hardhat/src/internal/core/providers/http.ts:49:19)
      at LocalAccountsProvider.request (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/hardhat/src/internal/core/providers/accounts.ts:188:34)
      at processTicksAndRejections (internal/process/task_queues.js:95:5)
      at EthersProviderWrapper.send (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20),
  method: 'call',
  transaction: {
    gasLimit: BigNumber { value: "100000" },
    to: '0x198478F870d97D62D640368D111b979d7CA3c38F',
    data: '0x6352211e0000000000000000000000000000000000000000000000000000000000000000',
    accessList: null
  }
}

but note that the nested error is ProviderError: execution reverted: ERC721: owner query for nonexistent token.

When the // use plain Ethers.js snippet for provider is used instead, it raises the expected exception:

$ npx hardhat run --no-compile scripts/test-owner-of-simple.js --network mainnet
Error! Error: call revert exception (method="ownerOf(uint256)", errorArgs=["ERC721: owner query for nonexistent token"], errorName="Error", errorSignature="Error(string)", reason="ERC721: owner query for nonexistent token", code=CALL_EXCEPTION, version=abi/5.5.0)
    at Logger.makeError (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/logger/src.ts/index.ts:225:28)
    at Logger.throwError (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/logger/src.ts/index.ts:237:20)
    at Interface.decodeFunctionResult (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/abi/src.ts/interface.ts:425:23)
    at Contract.<anonymous> (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/contracts/src.ts/index.ts:392:44)
    at step (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/contracts/lib/index.js:48:23)
    at Object.next (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/contracts/lib/index.js:29:53)
    at fulfilled (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/contracts/lib/index.js:20:58)
    at processTicksAndRejections (internal/process/task_queues.js:95:5) {
  reason: 'ERC721: owner query for nonexistent token',
  code: 'CALL_EXCEPTION',
  method: 'ownerOf(uint256)',
  errorArgs: [ 'ERC721: owner query for nonexistent token' ],
  errorName: 'Error',
  errorSignature: 'Error(string)',
  address: '0x198478f870d97d62d640368d111b979d7ca3c38f',
  args: [ 0 ],
  transaction: {
    data: '0x6352211e0000000000000000000000000000000000000000000000000000000000000000',
    to: '0x198478F870d97D62D640368D111b979d7CA3c38F',
    gasLimit: BigNumber { value: "100000" }
  }
}

Note that the error here is Error: call revert exception (method="ownerOf(uint256)", errorArgs=["ERC721: owner query for nonexistent token"],
whereas with the HardHat provider it was: ProviderError: execution reverted: ERC721: owner query for nonexistent token.
The checkError helper in ethers' JsonRpcProvider picks up on that execution reverted in the error message, and wraps it and raises UNPREDICTABLE_GAS_LIMIT instead. But one can still see the original error in err.error.

@nedgar
Copy link

nedgar commented Mar 8, 2022

My hardhat.config.js has:

require("@nomiclabs/hardhat-ethers");

// require("dotenv").config();

const { INFURA_KEY, PRIVATE_KEY } = process.env;

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: {
    version: "0.8.12",
    },
  },
  networks: {
    mainnet: {
      chainId: 1,
      url: "https://mainnet.infura.io/v3/" + INFURA_KEY,
      accounts: [PRIVATE_KEY],
    },
  },
};

@nedgar
Copy link

nedgar commented Mar 8, 2022

It can be reproduced with any ERC-721 contract, when the token ID does not exist, assuming the contract's ownerOf implementation requires it to exist (the usual OpenZeppelin and OpenSea tutorial contracts do). Other requires failures or explicit reverts would likely trigger this too, when it's a view or constant function being called or when using estimateGas.

@nedgar
Copy link

nedgar commented Mar 8, 2022

I added the following at the top of JsonRpcProvider's checkError, in the local compiled JS code at node_modules/@ethersproject/providers/lib/json-rpc-provider.js:

    console.log("checkError:", {method, error: {message: error.message, ...error}, params});

(the funkiness for error: is to avoid the default stringification of errors, to show all its properties).

Running my example above with the ethers config, it yields:

checkError: {
    method: 'call',
    error: {
      message: 'processing response error (body="{\\"jsonrpc\\":\\"2.0\\",\\"id\\":44,\\"error\\":{\\"code\\":3,\\"data\\":\\"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000294552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000000000\\",\\"message\\":\\"execution reverted: ERC721: owner query for nonexistent token\\"}}", error={"code":3,"data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000294552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000000000"}, requestBody="{\\"method\\":\\"eth_call\\",\\"params\\":[{\\"gas\\":\\"0x186a0\\",\\"to\\":\\"0x198478f870d97d62d640368d111b979d7ca3c38f\\",\\"data\\":\\"0x6352211e0000000000000000000000000000000000000000000000000000000000000000\\"},\\"latest\\"],\\"id\\":44,\\"jsonrpc\\":\\"2.0\\"}", requestMethod="POST", url="https://mainnet.infura.io/v3/27a2759c1c1b40c18cd5aa2d714414fd", code=SERVER_ERROR, version=web/5.5.1)',
      reason: 'processing response error',
      code: 'SERVER_ERROR',
      body: '{"jsonrpc":"2.0","id":44,"error":{"code":3,"data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000294552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000000000","message":"execution reverted: ERC721: owner query for nonexistent token"}}',
      error: Error: execution reverted: ERC721: owner query for nonexistent token
          at getResult (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:99:19)
          at processJsonFunc (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/web/src.ts/index.ts:363:22)
          at /Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/web/src.ts/index.ts:300:42
          at step (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/web/lib/index.js:33:23)
          at Object.next (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/web/lib/index.js:14:53)
          at fulfilled (/Users/nedgar/src/gitlab.com/carbonbasemvp/hamster-kingdom-nft/src/solidity/node_modules/@ethersproject/web/lib/index.js:5:58)
          at processTicksAndRejections (internal/process/task_queues.js:95:5) {
        code: 3,
        data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000294552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000000000'
      },
      requestBody: '{"method":"eth_call","params":[{"gas":"0x186a0","to":"0x198478f870d97d62d640368d111b979d7ca3c38f","data":"0x6352211e0000000000000000000000000000000000000000000000000000000000000000"},"latest"],"id":44,"jsonrpc":"2.0"}',
      requestMethod: 'POST',
      url: 'https://mainnet.infura.io/v3/27a2759c1c1b40c18cd5aa2d714414fd'
    },
    params: {
      transaction: {
        gasLimit: BigNumber { value: "100000" },
        to: '0x198478F870d97D62D640368D111b979d7CA3c38F',
        data: '0x6352211e0000000000000000000000000000000000000000000000000000000000000000',
        accessList: null
      },
      blockTag: 'latest'
    }
  }

so the first if branch in checkError is taken and it returns the nested error.data here.

With the hardhat config, it yields:

checkError: {
    method: 'call',
    error: {
      message: 'execution reverted: ERC721: owner query for nonexistent token',
      parent: undefined,
      name: 'ProviderError',
      code: 3,
      _isProviderError: true,
      data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000294552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000000000'
    },
    params: {
      transaction: {
        gasLimit: BigNumber { value: "100000" },
        to: '0x198478F870d97D62D640368D111b979d7CA3c38F',
        data: '0x6352211e0000000000000000000000000000000000000000000000000000000000000000',
        accessList: null
      },
      blockTag: 'latest'
    }
  }

so it ends up at that special case for UNPREDICTABLE_GAS_LIMIT at bottom, with the message matching execution reverted in the regex there.

@fvictorio
Copy link
Member

Thanks a lot @nedgar, this is really useful

@fvictorio fvictorio reopened this Mar 8, 2022
@fvictorio fvictorio added status:needs-research type:bug Something isn't working and removed status:needs-more-info There's not enough information to start working on this issue labels Mar 8, 2022
@nedgar
Copy link

nedgar commented Mar 9, 2022

I've put this in a standalone repo: https://github.com/nedgar/ethers-hardhat-error-handling-issue

@pheuberger
Copy link

Do we have an update where this error is coming from already?

@nedgar
Copy link

nedgar commented Apr 27, 2022

@pheuberger At the time of filing this, the string was coming from this line in JsonRpcProvider:

logger.throwError("cannot estimate gas; transaction may fail or may require manual gas limit", Logger.errors.UNPREDICTABLE_GAS_LIMIT, {

It's possible it has been fixed by this commit, fixing ethers-io/ethers.js#2603, but I have not had a chance to verify that.

@nedgar
Copy link

nedgar commented Apr 27, 2022

See comment above for context.

@pheuberger
Copy link

Thanks a lot @nedgar! Seems I glanced over the comments a little too quickly and missed that you already pointed out what the cause is. I'll update ethers and see if the error shows up again.

@rejnowskimikolaj
Copy link

Hey guys, is this issue being worked on? I have the same problem when connecting to private network (hyperledger besu). I never get any original revert message, always:

Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"ProviderError","code":-32000,"_isProviderError":true,"data":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001570726f706f73616c20646f65736e742065786973740000000000000000000000"}, method="estimateGas", transaction={"from":"0x3d1f605BB9838Ca14D9fDF2dE17D4dc114697261","to":"0x4586aA3Fe889F4572d92ed876a38D669F0D247f5","data":"0x943e821600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.5.1) at Logger.makeError (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/@ethersproject/logger/src.ts/index.ts:225:28) at Logger.throwError (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/@ethersproject/logger/src.ts/index.ts:237:20) at checkError (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:80:16) at EthersProviderWrapper.<anonymous> (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:562:20) at step (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:48:23) at Object.throw (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:29:53) at rejected (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:21:65) at processTicksAndRejections (node:internal/process/task_queues:96:5) { reason: 'cannot estimate gas; transaction may fail or may require manual gas limit', code: 'UNPREDICTABLE_GAS_LIMIT', error: ProviderError: Execution reverted at HttpProvider.request (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/hardhat/src/internal/core/providers/http.ts:49:19) at LocalAccountsProvider.request (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/hardhat/src/internal/core/providers/accounts.ts:187:34) at processTicksAndRejections (node:internal/process/task_queues:96:5) at EthersProviderWrapper.send (/Users/rejnol/src/uniswap/uniswap_wrapper/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20), method: 'estimateGas',

@nedgar
Copy link

nedgar commented May 20, 2022

@rejnowskimikolaj Are you calling estimateGas in this case, or is that being done implicitly? Check the error for any nested .error. Also make sure you're using the latest version of ethers.

@rejnowskimikolaj
Copy link

rejnowskimikolaj commented Jun 20, 2022

@nedgar this is done implicitly, before commiting the transaction. OFC I've checked the nested errors. There are no revert messages, only those general "UNPREDICTABLE_GAS_LIMIT" errors.

@rejnowskimikolaj
Copy link

this is my package.json:

"devDependencies": { "@ethersproject/solidity": "^5.5.0", "@nomiclabs/hardhat-ethers": "^2.0.6", "@nomiclabs/hardhat-waffle": "^2.0.1", "@openzeppelin/contracts": "^4.4.1", "@uniswap/lib": "^4.0.1-alpha", "@uniswap/v2-core": "^1.0.1", "@xplorfin/hardhat-solc-excludes": "^0.1.1", "chai": "^4.3.4", "ethereum-waffle": "^3.4.0", "ethers": "^5.6.9", "hardhat": "^2.9.9" }

@rejnowskimikolaj
Copy link

also, I've tried to debug it the same way you did here, and still there is no revert message.

checkError: { method: 'estimateGas', error: { message: 'Execution reverted', parent: undefined, name: 'ProviderError', code: -32000, _isProviderError: true, data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000316c6f636b2074696d6520686173206e6f7420657870697265642e20506c656173652074727920616761696e206c61746572000000000000000000000000000000' }, params: { transaction: { from: '0x8Aaf71012a096088b3069F440bb436CA1F630520', to: '0x9715568B3fb46E9fe6C46a3B0aEAD4A056D1BEfD', data: '0x580f39040000000000000000000000003d1f605bb9838ca14d9fdf2de17d4dc114697261', accessList: null } } }

@github-actions
Copy link
Contributor

This issue was marked as stale because it didn't have any activity in the last 30 days. If you think it's still relevant, please leave a comment indicating so. Otherwise, it will be closed in 7 days.

@github-actions github-actions bot added the Stale label Jul 20, 2022
@BayKeremm
Copy link
Contributor

I am having the same problem, for some reason I can sign transactions with one account but when I switch accounts it cannot predict gas anymore.

What I am using: local hardhat node running, I can sign transactions with the account I deployed the smart contract however I cannot sign transactions with other test accounts.

If anyone else got the same issue we could discuss why this is happening

@github-actions github-actions bot removed the Stale label Jul 22, 2022
@ErrorEater
Copy link

If you are using MetaMask: Settings/Advanced/Reset Account and then try again.

@rejnowskimikolaj
Copy link

hello, any updates on this issue?

@BayKeremm
Copy link
Contributor

I have solved the problem I was working on. An unpredictable gas limit message can be really misleading sometimes.
So here are a couple of things I have noticed in my project, that maybe could be of use to someone else:
- Make sure to check allowance if you are calling a function with any transfer involved between accounts or contracts. So this might involve asking users to give allowance to certain stuff, since, unlimited allowance is not safe.
- Check the account balances of the test accounts to see if they have the custom ERC20 token which you are trying to use and if there are enough minted tokens.

In general, an unpredictable gas limit message is due to you trying to use a function that has some other bits and quirks you need to consider that you miss. At least this was my case :D. So, if anyone still having this issue, take a step back and go over what should happen in the code and what is happening and question whether you understand it fully.

@nedgar
Copy link

nedgar commented Sep 18, 2022

Sorry for the delay in verifying the fix. I can confirm that as of ethers.js 5.6.2, my scenario above of issuing a call to a view function (which shouldn't have to estimate gas to begin with) now fails with a CALL_EXCEPTION instead of UNPREDICTABLE_GAS_LIMIT.

Using the standalone example of calling an ERC-721 contract's ownerOf(uint256 tokenId) with an invalid token ID, it now (correctly) fails as follows, with the original revert message from the contract available as reason:

Error: call revert exception; VM Exception while processing transaction: reverted with reason string "ERC721: owner query for nonexistent token" [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="ownerOf(uint256)", data="0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000294552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000000000", errorArgs=["ERC721: owner query for nonexistent token"], errorName="Error", errorSignature="Error(string)", reason="ERC721: owner query for nonexistent token", code=CALL_EXCEPTION, version=abi/5.7.0)
    at Logger.makeError (/Users/nedgar/src/github.com/nedgar/ethers-hardhat-error-handling-issue/node_modules/@ethersproject/logger/src.ts/index.ts:269:28)
    at Logger.throwError (/Users/nedgar/src/github.com/nedgar/ethers-hardhat-error-handling-issue/node_modules/@ethersproject/logger/src.ts/index.ts:281:20)
    at Interface.decodeFunctionResult (/Users/nedgar/src/github.com/nedgar/ethers-hardhat-error-handling-issue/node_modules/@ethersproject/contracts/node_modules/@ethersproject/abi/src.ts/interface.ts:427:23)
    at Contract.<anonymous> (/Users/nedgar/src/github.com/nedgar/ethers-hardhat-error-handling-issue/node_modules/@ethersproject/contracts/src.ts/index.ts:400:44)
    at step (/Users/nedgar/src/github.com/nedgar/ethers-hardhat-error-handling-issue/node_modules/@ethersproject/contracts/lib/index.js:48:23)
    at Object.next (/Users/nedgar/src/github.com/nedgar/ethers-hardhat-error-handling-issue/node_modules/@ethersproject/contracts/lib/index.js:29:53)
    at fulfilled (/Users/nedgar/src/github.com/nedgar/ethers-hardhat-error-handling-issue/node_modules/@ethersproject/contracts/lib/index.js:20:58)
    at processTicksAndRejections (internal/process/task_queues.js:95:5) {
  reason: 'ERC721: owner query for nonexistent token',
  code: 'CALL_EXCEPTION',
  method: 'ownerOf(uint256)',
  data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000294552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000000000',
  errorArgs: [ 'ERC721: owner query for nonexistent token' ],
  errorName: 'Error',
  errorSignature: 'Error(string)',
  address: '0x198478f870d97d62d640368d111b979d7ca3c38f',
  args: [ 0 ],
  transaction: {
    data: '0x6352211e0000000000000000000000000000000000000000000000000000000000000000',
    to: '0x198478F870d97D62D640368D111b979d7CA3c38F',
    gasLimit: BigNumber { _hex: '0x0186a0', _isBigNumber: true }
  }
}

@nedgar
Copy link

nedgar commented Sep 18, 2022

Since the original problem report was so ambiguous, I suggest treating this issue as "UNPREDICTABLE_GAS_LIMIT when calling a view function" and closing it as fixed.

@bohdanprog
Copy link

Hi, I had the same problem mentioned that does not return correct error and always: Error: cannot estimate gas; transaction may fail or may require manual gas limit.
I see that this is seemingly fixed in the case of view function, but in the case of transaction using gas it is not.

My solution is that, we have the returned error:
Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={“name”:“ProviderError”,“code”:-32000,“_isProviderError”:true,“data”:“0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001570726f706f73616c20646f65736e742065786973740000000000000000000000"}, method=“estimateGas”, transaction={“from”:“0x3d1f605BB9838Ca14D9fDF2dE17D4dc114697261”,“to”:“0x4586aA3Fe889F4572d92ed876a38D669F0D247f5”,“data”:“0x943e821600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001”,“accessList”:null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.5.1)

then we can try to refer to: error.error.data like this “data”:“0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001570726f706f73616c20646f65736e742065786973740000000000000000000000 and so we can decode this error.

I wrote such a function that helps me with this:
export function getRevertMsg(data: string) { const returnData = ethers.utils.defaultAbiCoder.decode([“string”], ethers.utils.hexDataSlice(data, 4)) console.log(“Revert message: “, returnData[0].length > 0 ? returnData[0] : “revert without reason”) }

I expect that this will help you !

@fvictorio
Copy link
Member

Hi everyone, I'm revisiting this issue after a long time, and this is what I found using the latest version of ethers:

  1. If you make a call to a view function that reverts, you get the proper reason string in the error message. In some old versions this wasn't working, but it seems to work fine now.
  2. When you make a gas estimation and the transaction reverts, you get the UNPREDICTABLE_GAS_LIMIT thing. This also happens with plain ethers. The returned error actually has the error reason, but it's kind of buried in the huge error: there's a reason field with it. You can also catch the error and log e.reason. I think it would be nice to include the error reason in the message, since that's what most users read, but at least the information is there.
  3. When you send a transaction but don't include a explicit gas limit, ethers will make a gas estimation first, so the previous item applies.

I'm going to close this now. If someone has some issue around this, please open a new issue with minimal reproduction steps.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type:bug Something isn't working
Projects
None yet
Development

No branches or pull requests

10 participants