8

I'm using the following function in my JS tests (with truffle) to move forward in time to test time dependent functions:

const timeTravel = function (time) {
  return new Promise((resolve, reject) => {
    web3.currentProvider.sendAsync({
      jsonrpc: "2.0",
      method: "evm_increaseTime",
      params: [time], // 86400 is num seconds in day
      id: new Date().getTime()
    }, (err, result) => {
      if(err){ return reject(err) }
      return resolve(result)
    });
  })
}

So then, I can do a test like this:

it("should not allow to buy tokens if crowdsale has finished", async function () {

    await timeTravel(100000) // Move forward in time so the crowdsale has finished
    await mineBlock() // workaround for https://github.com/ethereumjs/testrpc/issues/336

    try {
      await crowdsale.buyTokens(accounts[1],{from:accounts[1],value:1 * 10 ** 18});
    } catch (e) {
      return true;
    }
    throw new Error("I should never see this!")


  });

The problem is that this "time traveling to the future" is not transitory, meaning that testrpc will continue to be in a future block unless I stop testrpc and start it again.

I'd like to run a test in the future and then go back to continue running the automated test in the current block.

Supplying a negative number will obviously not go back to a previous block and there is no such thing as evm_decreaseTime.

| improve this question | | | | |
1

Just made a simple PR for this. Works for me!

https://github.com/trufflesuite/ganache-core/pull/95

| improve this answer | | | | |
1

You can take a snapshot of the EVM at the beginning of your test and revert the EVM to that snapshot at the end of your test, for example:

it("should not allow to buy tokens if crowdsale has finished", async function () {
    const snapshotId = web3.currentProvider.send({jsonrpc: "2.0", method: "evm_snapshot"});
    await timeTravel(100000); // Move forward in time so the crowdsale has finished
    await mineBlock(); // workaround for https://github.com/ethereumjs/testrpc/issues/336
    try {
        await crowdsale.buyTokens(accounts[1], {from:accounts[1], value: 1 * 10 ** 18});
    }
    catch (e) {
        web3.currentProvider.send({jsonrpc: "2.0", method: "evm_revert", params: [snapshotId]});
        return true;
    }
    throw new Error("I should never see this!");
});

BTW, this is exactly what truffle test does at the beginning and end of every contract clause (typically every JS file, though you can technically have several contract clauses in a single JS file) that it executes. So as an alternative to the solution above, you can simply put this specific test inside a contract clause:

contract("test", function(accounts) {
    it("should not allow to buy tokens if crowdsale has finished", async function () {
        ...
    });
});
| improve this answer | | | | |
0

evm_increaseTime accepts negative numbers, so you can decrease time by invoking as follows:

// decrease time by 1 day
web3.currentProvider.send({
  jsonrpc: "2.0", 
  method: "evm_increaseTime", 
  params: [-1440], 
  id: 0
});
| improve this answer | | | | |
  • 1
    Sorry, but that doesn't seem to be working. Passing a negative number to evm_increaseTime does nothing. Not getting any errors but not going back either. – pabloruiz55 Dec 8 '17 at 11:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.