You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Waffle+Chai测试ERC721智能合约时回滚断言失效问题

解决Chai回滚断言未生效的问题

我一眼就看出问题出在哪了——你在expect()里面多写了await,这直接导致Chai的回滚断言根本没机会生效!

核心原因:错误地提前执行了交易/调用

Chai Waffle的.to.be.reverted和.to.be.revertedWith()断言,需要接收一个未被执行的Promise(也就是还没加await的合约调用/交易)。如果在expect()内部加了await,会直接触发合约调用,一旦合约revert,这个异常会直接抛出来,测试框架会立刻判定测试失败,而不是让断言去验证这个预期的回滚。

修正你的测试代码

1. 非Owner调用失败的测试用例

把expect内部的await去掉:

it('should fail when non-owner calls the function', async () => { 
  let addGenesisHoldersTx = await myToken.addGenesisTokenHolderAddresses(genesisTokenHolders) 
  await addGenesisHoldersTx.wait(); 
  // 移除expect括号里的await,让断言处理交易执行
  await expect(myToken.connect(addr1).airdropTokensToGenesisHolders(1, 2)).to.be.revertedWith("Ownable: caller is not the owner"); 
}) 

2. Owner调用成功的测试用例

同样要去掉验证不存在Token时的await:

it('should succeed when called by the owner', async () => { 
  let addGenesisHoldersTx = await myToken.addGenesisTokenHolderAddresses(genesisTokenHolders) 
  await addGenesisHoldersTx.wait(); 
  let airdropTx = await myToken.connect(deployer).airdropTokensToGenesisHolders(1,2); 
  await airdropTx.wait(); 
  // 正常调用的ownerOf需要await获取结果,这部分没问题
  await expect(await myToken.ownerOf(1)).to.hexEqual(addr1.address) 
  await expect(await myToken.ownerOf(2)).to.hexEqual(addr2.address) 
  // 这里移除await,让断言捕获预期的revert
  await expect(myToken.ownerOf(1000)).to.be.reverted; 
}) 

额外说明

  • 对于预期正常执行的合约调用(比如ownerOf(1)),需要用await获取结果后再做断言;
  • 对于预期会revert的调用,必须把未执行的Promise传给expect,让Chai的断言逻辑去处理交易执行和异常捕获。

这样修改后,你的测试就能按照预期通过——断言会正确捕获revert,并验证错误信息是否符合预期,而不是直接抛出异常导致测试失败。

内容的提问来源于stack exchange,提问作者Craigson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 22:57:31