如何使用 truffle 控制台的 testrpc `evm_increaseTime` 参数?

How to use the testrpc `evm_increaseTime` parameter from truffle console?

我正在使用 truffle 和 testrpc 创建智能合约。在编写单元测试时,我希望更改块时间以模拟可能调用智能合约的不同时间。一套 evm_increaseTime inside truffle console 如何?

解决方案是覆盖 solidity 中的 now 关键字,将其设置为一个值,然后稍后在应用程序中使用该值(用于测试目的)。

通过示例扩展 OP 的答案(摘自 Status

我建议在正常情况下创建一个getTime()函数到return now,并在测试时设置一个可设置的时间。

SNTPlaceHolder.sol

/// @notice This function is overriden by the test Mocks.
function getTime() internal returns (uint256) {
    return now;
}

SNTPlaceHolderMock.sol

uint256 mock_time;

function SNTPlaceHolderMock(...)
        SNTPlaceHolder(...) {
    mock_time = now;
}

function getTime() internal returns (uint256) {
    return mock_time;
}

function setMockedTime(uint256 _t) public {
    mock_time = _t;
}

我们现在可以使用 await sntPlaceHolderMock.setMockedTime(t);

设置模拟时间
  1. 1.evm_increaseTime:增加下一个区块的时间。
  2. 2.evm_mine: 开采一个新区块。

这种时间旅行甚至不需要 Tardis 或 DeLorean。

让我解释一下这些函数是如何工作的:

每次开采一个新区块时,矿工都会为其添加一个时间戳。假设创建僵尸的交易在区块 5 中被开采。

接下来,我们调用 evm_increaseTime 但是,由于区块链是不可变的,因此无法修改现有区块。所以,当合约检查时间时,不会增加。

如果我们 运行 evm_mine,第 6 个区块被开采(并加上时间戳),这意味着,当我们让僵尸战斗时,智能合约将“看到”一天有通过。

综上所述,我们可以通过如下时间旅行来修复我们的测试:

await web3.currentProvider.sendAsync({
  jsonrpc: "2.0",
  method: "evm_increaseTime",
  params: [86400],  // there are 86400 seconds in a day
  id: new Date().getTime()
}, () => { });

web3.currentProvider.send({
    jsonrpc: '2.0',
    method: 'evm_mine',
    params: [],
    id: new Date().getTime()
});