Set gas limit on contract method in ethers.js
Asked Answered
D

4

26

Problem

I am trying to use a method of a contract on the test network (ropsten), but it fails due to this error:

reason: 'cannot estimate gas; transaction may fail or may require manual gas limit', code: 'UNPREDICTABLE_GAS_LIMIT'

Code

I created an instance of the smart contract and wanted to call it's register method:

const registrationContract = new ethers.Contract(ADDRESS, abi, signer);
const hashedDomain = utils.keccak256(utils.toUtf8Bytes(domain));

const register = await registrationContract.register(hashedDomain, walletAddress);

Does ethers.js provide a function to set the limit on the contract? Or can this be done otherwise? I didn't find one in the documentation.

Dropline answered 7/1, 2022 at 13:38 Comment(2)
I think the gasLimit is usually passed in the message argument. I don't know if that's always the case. Can you provide the contract you are trying to work with? For example with uniswap you set the gas limit to x with : uniswap.swapExactTokensForETH(tokenAmount, ethAmount, etc., {gasLimit: x})Morass
Here is a link to the contract: github.com/ensdomains/ens/blob/master/contracts/…Dropline
A
28

You can set the gas limit with an object as the last argument, for a simple transfer transaction, you could do something like this:

const tx = {
  to: toAddress,
  value: ethers.utils.parseEther(value),
  gasLimit: 50000,
  nonce: nonce || undefined,
};
await signer.sendTransaction(tx);

If you are doing a transaction to a smart contract, the idea is the same, but make sure you set the last parameter in one of your abi methods, example:

const tx = await contract.safeTransferFrom(from, to, tokenId, amount, [], {
  gasLimit: 100000,
  nonce: nonce || undefined,
});

This can fix the UNPREDICTABLE_GAS_LIMIT error, since informing it manually the ethers skips a rpc method call to the provider requesting the calculated gas_limit.

Arleen answered 7/1, 2022 at 13:55 Comment(4)
I already tried setting the gas limit on the contract, but the error remains.Dropline
Same error message?Arleen
Works now. Don't really know what changed, but I take what I can get.Dropline
You solved one of my biggest problems. Thanks you :)Unduly
L
12

Complementing the answer, when you define the gasLimit manually it's important to understand:

  1. the value configured is reserved and sent on contract call, so the caller account must have at least that value in his wallet;

  2. of course after the transaction completes the remaining Gas is returned to the caller wallet;

  3. so there is a problem when for the same transaction call, depending for example on the number of arguments, you have a wide range of gas values possibilities, and sometimes the value set is very high and disproportionate for small gas transactions.

So to workaround this problem and set dynamically gasLimit, used the function to estimate the transaction gas (estimateGas) from Ethers and then give an additional margin error percentage.

It could be something like this where gasMargin() calculates the final gas to pass in tx call (in this case just adds 10%).

const gasEstimated = await registrationContract.estimateGas.register(hashedDomain, walletAddress);

const register = await registrationContract.register(hashedDomain, walletAddress, {
      gasLimit: Math.ceil(gasMargin(gasEstimated, 1.1)) 
    });
Lilian answered 30/4, 2022 at 11:50 Comment(0)
J
2

const gasPrice = signer.gasPrice();

const gasLimit = contract.estimateGas.method(parameter);

const tx = contract. Method(parameter,{gasLimit:gasLimit,gasPrice:gasPrice});

Judgemade answered 8/9, 2022 at 3:43 Comment(0)
O
-1

You can make a helper function to increase gas limit by a certain amount:

const increaseGasLimit = (estimatedGasLimit: BigNumber) => {
  return estimatedGasLimit.mul(130).div(100) // increase by 30%
}

And use it like this:

const estimatedGas = await contract.estimateGas.method(args)
const tx = await contract.method(args, { gasLimit: increaseGasLimit(estimatedGas) })
Overnice answered 7/9, 2022 at 21:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.