Solidity时间旅行测试失败:CryptoZombies攻击用例Truffle测试报错
问题原因
- 报错核心是你使用的Truffle v5.4.17对应的web3版本中,
web3.currentProvider.send()是回调风格API,不支持直接用await调用,必须传入回调函数作为第二个参数,原实现未传回调就触发了callback is not a function错误。 - 原
increase方法中evm_mine的调用未加await,即使修复第一个调用的报错,也会出现时间调整未即时生效的问题,导致攻击冷却校验不通过。 - 你的测试用例存在隐藏缺陷:调用
attack方法时没有将返回值赋值给result,后续断言用的result还是第二次创建僵尸的返回结果,就算时间问题解决,断言也不符合预期。
解决方案
方案1:修改自定义increase实现
将回调风格的send调用封装为Promise适配await,修改后的代码如下:
async function increase(duration) { // 封装RPC调用为Promise格式兼容await const sendRPC = (payload) => { return new Promise((resolve, reject) => { web3.currentProvider.send(payload, (error, response) => { if (error) return reject(error) resolve(response) }) }) } // 调整EVM时间 await sendRPC({ jsonrpc: "2.0", method: "evm_increaseTime", params: [duration], id: new Date().getTime() }); // 挖矿出块使时间调整生效 await sendRPC({ jsonrpc: '2.0', method: 'evm_mine', params: [], id: new Date().getTime() }) }
方案2:使用Truffle官方测试工具(更稳定)
Truffle官方提供了封装好的时间操作工具@truffle/test-helpers,无需自己实现RPC调用,安装后直接导入即可使用和原调用逻辑完全一致的time.increase方法,兼容性更好。
修复测试用例隐藏缺陷
将测试用例中调用attack的行修改为:
result = await contractInstance.attack(firstZombieId, secondZombieId, {from: alice});
确保后续断言的是攻击交易的执行状态。
内容的提问来源于stack exchange,提问作者DeepSports
相关产品推荐
相关产品推荐

