今天在hardhat环境中使用etherjs调用智能合约出现了cannot estimate gas; transaction may fail or may require manual gas limit这样的错误排查了一天,这里记录一下排查的步骤。

网络环境是georli测试网

方法调用和报错如下:

let tx2 = await gravatarWithSigner.createGravatar('Lucas2', 'https://thegraph.com/img/team/bw_Lucas.jpg');Uncaught: Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (error={"reason":"execution reverted","code":"UNPREDICTABLE_GAS_LIMIT","method":"estimateGas","transaction":{"from":"0xBA8B604410ca76AF86BDA9B00Eb53B65AC4c41AC","maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x59682f00"},"maxFeePerGas":{"type":"BigNumber","hex":"0x5968464a"},"to":"0x964F658FC863BAceFC719b85e8730fbc11c86ce4","data":"0xcdb3344a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000064c75636173320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a68747470733a2f2f74686567726170682e636f6d2f696d672f7465616d2f62775f4c756361732e6a706700000000000000000000000000000000000000000000","type":2,"accessList":null},"error":{"name":"ProviderError","_stack":"ProviderError: HttpProviderError\nat HttpProvider.request (D:\\workspace\\gambo\\subgraph-example\\node_modules\\hardhat\\src\\internal\\core\\providers\\http.ts:78:19)\nat LocalAccountsProvider.request (D:\\workspace\\gambo\\subgraph-example\\node_modules\\hardhat\\src\\internal\\core\\providers\\accounts.ts:187:34)\nat processTicksAndRejections (internal/process/task_queues.js:95:5)\nat async EthersProviderWrapper.send (D:\\workspace\\gambo\\subgraph-example\\node_modules\\@nomiclabs\\hardhat-ethers\\src\\internal\\ethers-provider-wrapper.ts:13:20)","code":-32000,"_isProviderError":true}}, tx={"data":"0xcdb3344a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000064c75636173320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a68747470733a2f2f74686567726170682e636f6d2f696d672f7465616d2f62775f4c756361732e6a706700000000000000000000000000000000000000000000","to":{},"from":"0xBA8B604410ca76AF86BDA9B00Eb53B65AC4c41AC","type":2,"maxFeePerGas":{"type":"BigNumber","hex":"0x5968464a"},"maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x59682f00"},"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.7.0)at Logger.throwError (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\logger\src.ts\index.ts:281:20)at Logger.makeError (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\logger\src.ts\index.ts:269:28) {reason: 'cannot estimate gas; transaction may fail or may require manual gas limit',code: 'UNPREDICTABLE_GAS_LIMIT',error: Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (reason="execution reverted", method="estimateGas", transaction={"from":"0xBA8B604410ca76AF86BDA9B00Eb53B65AC4c41AC","maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x59682f00"},"maxFeePerGas":{"type":"BigNumber","hex":"0x5968464a"},"to":"0x964F658FC863BAceFC719b85e8730fbc11c86ce4","data":"0xcdb3344a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000064c75636173320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a68747470733a2f2f74686567726170682e636f6d2f696d672f7465616d2f62775f4c756361732e6a706700000000000000000000000000000000000000000000","type":2,"accessList":null}, error={"name":"ProviderError","_stack":"ProviderError: HttpProviderError\nat HttpProvider.request (D:\\workspace\\gambo\\subgraph-example\\node_modules\\hardhat\\src\\internal\\core\\providers\\http.ts:78:19)\nat LocalAccountsProvider.request (D:\\workspace\\gambo\\subgraph-example\\node_modules\\hardhat\\src\\internal\\core\\providers\\accounts.ts:187:34)\nat processTicksAndRejections (internal/process/task_queues.js:95:5)\nat async EthersProviderWrapper.send (D:\\workspace\\gambo\\subgraph-example\\node_modules\\@nomiclabs\\hardhat-ethers\\src\\internal\\ethers-provider-wrapper.ts:13:20)","code":-32000,"_isProviderError":true}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.7.2)at Logger.makeError (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\logger\src.ts\index.ts:269:28)at Logger.throwError (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\logger\src.ts\index.ts:281:20)at checkError (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\providers\src.ts\json-rpc-provider.ts:78:20)at EthersProviderWrapper. (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\providers\src.ts\json-rpc-provider.ts:642:20)at step (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:48:23)at Object.throw (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:29:53)at rejected (D:\workspace\gambo\subgraph-example\node_modules\@ethersproject\providers\lib\json-rpc-provider.js:21:65)at processTicksAndRejections (internal/process/task_queues.js:95:5) {reason: 'execution reverted',code: 'UNPREDICTABLE_GAS_LIMIT',method: 'estimateGas',transaction: {from: '0xBA8B604410ca76AF86BDA9B00Eb53B65AC4c41AC',maxPriorityFeePerGas: BigNumber { value: "1500000000" },maxFeePerGas: BigNumber { value: "1500005962" },to: '0x964F658FC863BAceFC719b85e8730fbc11c86ce4',data: '0xcdb3344a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000064c75636173320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a68747470733a2f2f74686567726170682e636f6d2f696d672f7465616d2f62775f4c756361732e6a706700000000000000000000000000000000000000000000',type: 2,accessList: null},error: ProviderError: HttpProviderErrorat HttpProvider.request (D:\workspace\gambo\subgraph-example\node_modules\hardhat\src\internal\core\providers\http.ts:78:19)at LocalAccountsProvider.request (D:\workspace\gambo\subgraph-example\node_modules\hardhat\src\internal\core\providers\accounts.ts:187:34)at processTicksAndRejections (internal/process/task_queues.js:95:5)at async EthersProviderWrapper.send (D:\workspace\gambo\subgraph-example\node_modules\@nomiclabs\hardhat-ethers\src\internal\ethers-provider-wrapper.ts:13:20)},tx: {data: '0xcdb3344a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000064c75636173320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a68747470733a2f2f74686567726170682e636f6d2f696d672f7465616d2f62775f4c756361732e6a706700000000000000000000000000000000000000000000',to: Promise {'0x964F658FC863Bxxxxxxxxx85e8730fbc11c86ce4',[Symbol(async_id_symbol)]: 1302,[Symbol(trigger_async_id_symbol)]: 1301,[Symbol(destroyed)]: [Object]},from: '0xBA8B6044xxxxxxxxDA9B00Eb53B65AC4c41AC',type: 2,maxFeePerGas: BigNumber { value: "1500005962" },maxPriorityFeePerGas: BigNumber { value: "1500000000" },nonce: Promise {19,[Symbol(async_id_symbol)]: 1517,[Symbol(trigger_async_id_symbol)]: 1326,[Symbol(destroyed)]: [Object]},gasLimit: Promise { [Circular *1],[Symbol(async_id_symbol)]: 1554,[Symbol(trigger_async_id_symbol)]: 1525,[Symbol(destroyed)]: [Object]},chainId: Promise {5,[Symbol(async_id_symbol)]: 1555,[Symbol(trigger_async_id_symbol)]: 1326,[Symbol(destroyed)]: [Object]}}}

在网上搜索关键字很多人说是手续费的设置问题。于是增加了gasLimit和gasPrices的配置。

await gravatarWithSigner.createGravatar('Lucas2', 'https://thegraph.com/img/team/bw_Lucas.jpg', {gasLimit: 2400000,gasPrice: ethers.utils.parseUnits('9.0', 'gwei')});{type: 2,chainId: 5,nonce: 19,maxPriorityFeePerGas: BigNumber { value: "9000000000" },maxFeePerGas: BigNumber { value: "9000000000" },gasPrice: null,gasLimit: BigNumber { value: "2400000" },to: '0x9xxxxxxxxxxxxx9b85e8730fbc11c86ce4',value: BigNumber { value: "0" },data: '0xcdb3344a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000064c75636173320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a68747470733a2f2f74686567726170682e636f6d2f696d672f7465616d2f62775f4c756361732e6a706700000000000000000000000000000000000000000000',accessList: [],hash: '0x212337d352d0b914e7940xxxxxxxxxxxxxx8e1f770c3a93de14fe076991eb3',v: 0,r: '0x0cacfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxeb0687abbdb0f7c32322',s: '0x73c66e3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxb6b42020c16535d6e5977b94',from: '0xxxxxxxxxxxxxxxxxxx',confirmations: 0,wait: [Function (anonymous)]}

没有报错,看似问题是解决了!但是通过返回的交易hash,在etherscan上找不到这笔交易!好像这笔交易丢失了一样!再仔细观察一下上面的报错cannot estimate gas; transaction may fail or may require manual gas limit,“交易可能失败或需要手动设置gas”,有没有可能是我们调用智能合约的时候出错了呢!

function createGravatar(string calldata _displayName, string calldata _imageUrl) public {require(ownerToGravatar[msg.sender] == 0);gravatars.push(Gravatar(msg.sender, _displayName, _imageUrl));uint id = gravatars.length - 1;gravatarToOwner[id] = msg.sender;ownerToGravatar[msg.sender] = id;emit NewGravatar(id, msg.sender, _displayName, _imageUrl);}

以上是我们调用的智能合约方法,通过分析代码我们发现每一个智能合约只能调用一次,于是我又调用了合约另外一个方法。此方法并不会出现交易失败的问题!然而返回的hash值依旧查询不到!

现在怀疑是账号的问题,所以尝试换个账号调用智能合约!

先通过matemask给第二个账号转一定的georli eth防止没有手续费!但是又出现了奇怪的问题!

[ethjs-query] while formatting outputs from RPC ‘{“value”:{“code”:-32000,”message”:”replacement transaction underpriced”}}’

连转账都转不出去,这就很可能是这个账号的问题了!

网上有很多人遇到过这个问题,大部分都说要增加手续费,然而我这边尝试过以后问题依旧!

最后看到这篇文章

解决replacement transaction underpriced以太坊交易异常

这里面除了手续费的问题还提到了nonce值

大体的原因就是由于这个账号前期有某一笔交易一直处于pending状态,如果这笔交易不被覆盖掉,那么后续所有的交易都无法成功。覆盖的方法就是修改交易的nonce值!

通过修改mateMask的nonce值修复replacement transaction underpriced的问题

通过修改nonce值使得交易成功后,再换第二个账号调用合约的createGravatar方法,成功调用!

再用第一个账号调用合约的其他方法,同样是成功调用!

总结一下出现cannot estimate gas或者是交易丢失的问题所在!

  1. 交易费设置的问题(并没有在本次出现的问题中的得到印证)!

  1. 排查是否是合约调用本身出现了问题。

  1. 由于当前帐号一直有交易处于pending状态需要在matemask中进行更高nonce值的交易以覆盖之前的交易。