简体   繁体   English

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

[英]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:我正在尝试在测试网络(ropsten)上使用合约方法,但由于此错误而失败:

reason: 'cannot estimate gas;原因:'无法估算气体; transaction may fail or may require manual gas limit', code: 'UNPREDICTABLE_GAS_LIMIT'交易可能会失败或可能需要手动限制气体”,代码:“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? ethers.js是否提供 function 来设置合约限制? 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:作为答案的补充,当您手动定义 gasLimit 时,了解以下内容很重要:

  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;当然交易完成后剩余的 Gas 会返还给调用者钱包;

  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.所以当同一个交易调用时会出现问题,例如取决于 arguments 的数量,你有广泛的 gas 值可能性,有时值设置非常高并且与小 gas 交易不成比例。

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.因此,为了解决这个问题并动态设置 gasLimit,使用 function 来估计来自 ETH 的交易气体(estimateGas),然后给出额外的保证金错误百分比。

It could be something like this where gasMargin() calculates the final gas to pass in tx call (in this case just adds 10%).可能是这样的,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)) 
    });

You can set the gas limit with an object as the last argument, for a simple transfer transaction, you could do something like this:您可以使用 object 作为最后一个参数来设置气体限制,对于简单的转账交易,您可以执行以下操作:

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

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.这可以修复 UNPREDICTABLE_GAS_LIMIT 错误,因为手动通知它 ethers 会跳过向提供程序请求计算的 gas_limit 的 rpc 方法调用。

You can make a helper function to increase gas limit by a certain amount:您可以制作一个助手 function 以将气体限制增加一定量:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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