在 ethers.js 中设置合约方法的 Gas 限制

Gh0*_*05d 26 javascript ethereum ether ethers.js

问题

我试图在测试网络(ropsten)上使用合约的方法,但由于以下错误而失败:

原因:'无法估计气体;交易可能失败或可能需要手动气体限制',代码:'UNPREDICTABLE_GAS_LIMIT'

代码

我创建了一个智能合约的实例,并想调用它的注册方法:

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

const register = await registrationContract.register(hashedDomain, walletAddress);
Run Code Online (Sandbox Code Playgroud)

ethers.js是否提供了对合约设置限制的功能?或者可以用其他方式做到这一点吗?我在文档中没有找到。

小智 28

您可以使用对象作为最后一个参数来设置气体限制,对于简单的转移交易,您可以执行以下操作:

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

如果您正在对智能合约进行交易,其想法是相同的,但请确保在 abi 方法之一中设置最后一个参数,例如:

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

这可以修复 UNPREDICTABLE_GAS_LIMIT 错误,因为手动通知它,以太会跳过对请求计算的 Gas_limit 的提供者的 rpc 方法调用。

  • 你解决了我最大的问题之一。感谢您 :) (3认同)

小智 12

作为答案的补充,当您手动定义gasLimit时,了解以下内容很重要:

  1. 配置的值被保留并在合约调用时发送,因此调用者帐户的钱包中必须至少有该值;

  2. 当然,交易完成后,剩余的Gas会返回到调用者的钱包中;

  3. 因此,当对于同一个交易调用时,例如根据参数的数量,您可能会遇到各种各样的 Gas 值,有时设置的值非常高,并且对于小型 Gas 交易来说不成比例。

因此,为了解决这个问题并动态设置gasLimit,使用该函数来估计以太币的交易气体(estimateGas),然后给出额外的保证金误差百分比。

可能是这样的,gasMargin() 计算在 tx 调用中传递的最终气体(在本例中仅添加 10%)。

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

const register = await registrationContract.register(hashedDomain, walletAddress, {
      gasLimit: Math.ceil(gasMargin(gasEstimated, 1.1)) 
    });
Run Code Online (Sandbox Code Playgroud)