简体   繁体   中英

Set gas limit on contract method in ethers.js

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 .

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)) 
    });

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.

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) })

const gasPrice = signer.gasPrice();

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM