You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Ethers still tries to estimate gas even when passing manual gasLimit #2603
Describe the bug
I'm trying to call a contract method with an unpredictable gas limit, however if I try to call it and pass the gasLimit manually I get get a "Error: cannot estimate gas; transaction may fail or may require manual gas limit" error.
Maybe I'm missing something but shouldn't ethers skip estimating gas if it's passed manually?
Reproduction steps
You can test with the following contract in rinkeby:
const CONTRACT = "0x10539a06b047259f247f8c622430c22803821A00";
const ABI = [
'function stakeOf(address _owner) public view returns (uint256[] memory)'
];
// using JsonRpcProvider as an example, but I've tried with metamask as well and same issue
const provider =new ethers.providers.JsonRpcProvider(
"provider URL"
);
const signer = provider.getSigner();
const contract = new ethers.Contract(CONTRACT, ABI, signer);
contract.stakeOf("0x73257cE508dBB94Ff78C27381FddD42FB7266Ba4", {
gasLimit: '50000000',
}),
Result
Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"ProviderError","code":3,"_isProviderError":true,"data":"0x4e487b710000000000000000000000000000000000000000000000000000000000000032"}, method="call", transaction={"from":"0x73257cE508dBB94Ff78C27381FddD42FB7266Ba4","gasLimit":{"type":"BigNumber","hex":"0x02faf080"},"to":"0x10539a06b047259f247f8c622430c22803821A00","data":"0x4262336000000000000000000000000073257ce508dbb94ff78c27381fddd42fb7266ba4","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.5.1)
//...
method: 'call',
transaction: {
from: '0x73257cE508dBB94Ff78C27381FddD42FB7266Ba4',
gasLimit: BigNumber { value: "50000000" },
to: '0x10539a06b047259f247f8c622430c22803821A00',
data: '0x4262336000000000000000000000000073257ce508dbb94ff78c27381fddd42fb7266ba4',
accessList: null
}
}
Environment:
Node: v14.17.4
This happens in both node and browser environments.
This should be fixed now, as the error checking spelunks through the object looking for the component that has both a message with the word "reverted" somewhere within it and has a data that is valid hex data.
This breaks my test code for catching call exceptions, which was working with [email protected]. Example output:
AssertionError: Expected transaction to be reverted with EXCEPTION_MESSAGE, but other exception was thrown: Error: missing revert data in call exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (error={"stackTrace": [...]
@nataouze That was a bug; a call should never through a call exception (in ethers v5; in v6 it comes back as a CALL_EXCEPTION Error with a data property); it is always supposed to return the data the node sent back, but due to changes in the error format some backends were breaking that. But against Geth that should not have happened, for example.
To detect an error was thrown by a contract, the canonical way is to check the length of the bytes returned; if it is congruent to 0 mod 32 then it is not an error and if it is congruent to 4 mod 32 then it is an error, with the first 4 bytes as the selector.
Your tests should have received a lot of false negatives in the previous version of ethers?
@nataouze I've added context to discussion #2849 to help explain what is going on and will be keeping that up to date if you want to hop over there. :)
Activity
ricmoo commentedon Jan 26, 2022
The automatic gasLimit population is only performed for send transactions, and your method is a call (as it is a
view).That error means the call is reverting, although I agree, it’s weird it would mention unpredictable gas.
More robust JSON-RPC error handling for reverted executions (#2603).
ricmoo commentedon Mar 26, 2022
This should be fixed now, as the error checking spelunks through the object looking for the component that has both a
messagewith the word "reverted" somewhere within it and has adatathat is valid hex data.nataouze commentedon Mar 26, 2022
This breaks my test code for catching call exceptions, which was working with
[email protected]. Example output:ricmoo commentedon Mar 26, 2022
@nataouze That was a bug; a call should never through a call exception (in ethers v5; in v6 it comes back as a CALL_EXCEPTION Error with a data property); it is always supposed to return the data the node sent back, but due to changes in the error format some backends were breaking that. But against Geth that should not have happened, for example.
To detect an error was thrown by a contract, the canonical way is to check the length of the bytes returned; if it is congruent to 0 mod 32 then it is not an error and if it is congruent to 4 mod 32 then it is an error, with the first 4 bytes as the selector.
Your tests should have received a lot of false negatives in the previous version of ethers?
Does that make sense?
nataouze commentedon Mar 26, 2022
@ricmoo I am not totally clear on what you describe. I didn't get false negatives in the past.
For context, I am using hardhat evm ([email protected]). My tests are using waffle, in this case the matcher
revertedWith.The issue arises when updating from
[email protected]to[email protected]ricmoo commentedon Mar 30, 2022
@nataouze I've added context to discussion #2849 to help explain what is going on and will be keeping that up to date if you want to hop over there. :)
nedgar commentedon Sep 18, 2022
Thanks for the fix @ricmoo. I've (finally) verified it -- see NomicFoundation/hardhat#2248 (comment)
More robust JSON-RPC error handling for reverted executions (ethers-i…