Solidity时间旅行测试失败



我正在学习CryptoZombies教程,但在通过其中一个测试时遇到了问题。测试如下:

it("zombies should be able to attack another zombie", async () => {
let result;
result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
const firstZombieId = result.logs[0].args.zombieId.toNumber();
result = await contractInstance.createRandomZombie(zombieNames[1], {from: bob});
const secondZombieId = result.logs[0].args.zombieId.toNumber();
await time.increase(time.duration.days(1));
await contractInstance.attack(firstZombieId, secondZombieId, {from: alice});
expect(result.receipt.status).to.equal(true);
})

本质上,创建僵尸1,创建僵尸2,快进一天,让僵尸1攻击僵尸2(因为僵尸创建和允许附加之间有一段冷却期(,最后断言智能合约能够执行。

测试失败,出现了一条无用的错误消息:

1) Contract: CryptoZombies
zombies should be able to attack another zombie:
Uncaught TypeError: callback is not a function
at /home/deepsports/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/packages/provider/wrapper.js:107:1
at XMLHttpRequest.request.onreadystatechange (/home/deepsports/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-providers-http/lib/index.js:98:1)
at XMLHttpRequestEventTarget.dispatchEvent (/home/deepsports/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:1)
at XMLHttpRequest.exports.modules.996763.XMLHttpRequest._setReadyState (/home/deepsports/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:208:1)
at XMLHttpRequest.exports.modules.996763.XMLHttpRequest._onHttpResponseEnd (/home/deepsports/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:318:1)
at IncomingMessage.<anonymous> (/home/deepsports/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:289:47)
at endReadableNT (internal/streams/readable.js:1334:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21)

作为背景,我使用:

  • 松露v4.4.17
  • 固结度0.4.25
  • 节点v14.18.0(如果有用的话?(

stacktrace有点难以解析,因为在我的实际代码中没有引用任何行。通过消除过程,能够确认是这一行代码导致了故障:await time.increase(time.duration.days(1));

它调用这个代码(作为教程的一部分创建(:

async function increase(duration) {
//first, let's increase time
await web3.currentProvider.send({
jsonrpc: "2.0",
method: "evm_increaseTime",
params: [duration], // there are 86400 seconds in a day
id: new Date().getTime()
});
//next, let's mine a new block
web3.currentProvider.send({
jsonrpc: '2.0',
method: 'evm_mine',
params: [],
id: new Date().getTime()
})
}

CryptoZombies似乎在模仿一个不推荐使用的web3版本(我猜他们也使用了sendAsync,这在CZ教程中,而不是在你的代码中(,这本可以在那里工作。

但是,正如本GitHub问题中所述,web3.currentProvider.send()现在需要一个回调参数,而无法使用await解决。

// no callback, fails
await web3.currentProvider.send({
jsonrpc: "2.0",
method: "evm_increaseTime",
params: [duration],
id: new Date().getTime()
});

工作解决方案:

async function increase(duration) {
return new Promise((resolve, reject) => {
web3.currentProvider.send({
jsonrpc: "2.0",
method: "evm_increaseTime",
params: [duration],
id: new Date().getTime()
}, (err, result) => {
// second call within the callback
web3.currentProvider.send({
jsonrpc: '2.0',
method: 'evm_mine',
params: [],
id: new Date().getTime()
}, (err, result) => {
// need to resolve the Promise in the second callback
resolve();
});
});
});
}

注意:不要将其与其他能够使用await解决的web3send()方法(如contract.methods.foo().send()(混淆

最新更新