I'm getting a gas limit error when calling ethers web3js on a view/ read-only blockchain function

Viewed 3689

Uncaught (in promise) Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"code":-32000,"message":"execution reverted"}, method="call" code=UNPREDICTABLE_GAS_LIMIT) error.

I am definitely calling a read-only function. The function is this:

function vaultSize(uint256 vaultId) public view virtual returns (uint256) {
    return
        store.isD2Vault(vaultId)
            ? store.d2Holdings(vaultId)
            : store.holdingsLength(vaultId).add(
                store.reservesLength(vaultId)
            );
}

If that matters. I don't understand why this gas limit error is even happening or how to fix it and I feel like debugging is so hard when it's not my own contract because the revert reason is never obvious.

Here's how I'm calling it in javascript.

await contract.vaultSize(0)

I don't see why this is happening. This is public code in a contract that is obviously working with thousands of transactions a day.

The address is "0xdaa17a5f60E94d5f97968aa1E790c164e65c97Be"

2 Answers

I was able to reproduce the issue with web3.js, which means that the error origins from contract (not from your JS implementation).

const contract = new web3.eth.Contract(jsonAbi, '0xdaa17a5f60E94d5f97968aa1E790c164e65c97Be');
const result = await contract.methods.vaultSize(0).call(); // throws "execution reverted"

The Solidity code expects the store address to implement the IXStore, but the value of store is 0x0. There's no contract on the zero address.

So when the contract calls store.isD2Vault(vauldId), it expects a bool response, but it doesn't get any. So the call fails.

Solution: Set the store value to an implementation of an IXStore interface and this revert will be solved.

Note that it's a large set of contracts, so if it's not properly tested, it's probable that there's more logical errors that might cause other reverts.

I ran into this issue, and I solved it by removing the gas property from the contract ABI.

For example, part of my ABI looked like this:

{
  "name": "get_virtual_price",
  "outputs": [
    {
      "type": "uint256",
      "name": ""
    }
  ],
  "inputs": [],
  "stateMutability": "view",
  "type": "function",
  "gas": 1011891
}

And I modified it to look like this, just removed gas:

{
  "name": "get_virtual_price",
  "outputs": [
    {
      "type": "uint256",
      "name": ""
    }
  ],
  "inputs": [],
  "stateMutability": "view",
  "type": "function"
}

Surprisingly enough, ethers was happy and didn't complain about being out of gas after that.

Related