在视图/只读区块链函数上调用 ethers web3js 时出现气体限制错误

Posted

技术标签:

【中文标题】在视图/只读区块链函数上调用 ethers web3js 时出现气体限制错误【英文标题】:I'm getting a gas limit error when calling ethers web3js on a view/ read-only blockchain function 【发布时间】:2021-08-04 23:01:42 【问题描述】:

未捕获(承诺)错误:无法估计气体;交易可能会失败或可能需要手动限制气体 (error="code":-32000,"message":"execution reverted", method="call" code=UNPREDICTABLE_GAS_LIMIT) 错误。

我肯定是在调用一个只读函数。函数是这样的:

function vaultSize(uint256 vaultId) public view virtual returns (uint256) 
    return
        store.isD2Vault(vaultId)
            ? store.d2Holdings(vaultId)
            : store.holdingsLength(vaultId).add(
                store.reservesLength(vaultId)
            );

如果这很重要。我不明白为什么会发生这种气体限制错误或如何修复它,而且我觉得调试非常困难,因为这不是我自己的合同,因为恢复原因从来都不是显而易见的。

这是我在 javascript 中的调用方式。

await contract.vaultSize(0)

我不明白为什么会这样。这是合约中的公共代码,显然每天要处理数千笔交易。

地址是“0xdaa17a5f60E94d5f97968aa1E790c164e65c97Be”

【问题讨论】:

请用最小的reproducible代码示例编辑您的问题,该示例会引发错误。 我以为就是这样。我的意思是我不希望有人为了也有这个错误而不得不部署整个合同。但是我的整个代码只是调用了该合约的 vaultSize 方法并且它不起作用。我应该只分享合约地址,看看是否有其他人可以用以太币以同样的方式调用它? 如果合约已经部署在公网,地址应该足够了。 好的,我添加了。它是“0xdaa17a5f60E94d5f97968aa1E790c164e65c97Be”; 【参考方案1】:

我能够通过web3.js 重现该问题,这意味着错误源自合同(而不是您的 JS 实现)。

const contract = new web3.eth.Contract(jsonAbi, '0xdaa17a5f60E94d5f97968aa1E790c164e65c97Be');
const result = await contract.methods.vaultSize(0).call(); // throws "execution reverted"

Solidity 代码期望store 地址实现IXStore,但store 的值是0x0。零地址没有合约。

因此,当合约调用store.isD2Vault(vauldId) 时,它期望得到bool 响应,但它没有得到任何响应。所以调用失败。

解决方案:将store 值设置为IXStore 接口的实现,即可解决此还原问题。

请注意,它是一大堆合约,因此如果没有正确测试,很可能存在更多可能导致其他还原的逻辑错误。

【讨论】:

太棒了,非常感谢您的检查。我知道代码超级长而且复杂。虽然它被破坏是令人困惑的,因为这个函数每周被合约中的其他函数成功调用数百次。该合同是否因为它是代理合同的实施者而失败?代理etherscan.io/address/… 调用此函数。这是否以某种方式为“存储”变量提供了一个我无法通过直接调用实现者来访问的值?他们的 web3 网站似乎可以正常运行。 我只是将我的代码更改为使用相同的 ABI 但使用代理的地址,现在它可以工作了!我早该想到的。我查看了代理代码,似乎它以某种方式扰乱了存储,当像我刚刚做的那样直接调用时不会改变存储。不知道它是如何工作的,但我想我应该找到有关代理内存的资源来阅读!再次感谢伙计:)你很棒。 当代理委托调用时,它使用实现的字节码(在您的情况下为0xdaa17...)但存储代理。并且代理的存储可能设置了值......所以你所说的代理是有道理的。

以上是关于在视图/只读区块链函数上调用 ethers web3js 时出现气体限制错误的主要内容,如果未能解决你的问题,请参考以下文章

使用Rust模拟ethers.js中的parseUnits

使用Rust模拟ethers.js中的parseUnits

区块链-前端交互第四篇:认识 ethers.js并运行测试代码

区块链-前端交互第四篇:认识 ethers.js并运行测试代码

java调用区块链智能合约

使用Ganache,web3js和remix在个人区块链上部署并调用合约