7

Any tips on how to simulate real network conditions on the testrpc testing client using truffle? I have some functions that look at blocknumber and try to deal with passing time. Has anyone come up with a good way to test these kind of things?

I'm wondering if just calling some null transactions in a loop with increase the block number accordingly. Any info on the inner workings of these things would be appreciated.

12

By default, every transaction called in testrpc is immediately mined and the block height will increase. The time it takes to mine each block can be set as a command line option when starting testrpc using -b or --blocktime

In addition, testrpc provides a custom rpc method you can use to manipulate the block height:

evm_mine : Force a block to be mined. Takes no parameters. Mines a block independent of whether or not mining is started or stopped.

Testrpc's custom methods can be called from web3 using web3.currentProvider.sendAsync() like so:

web3.currentProvider.sendAsync({
  jsonrpc: "2.0",
  method: "evm_mine",
  id: 12345
}, function(err, result) {
  // this is your callback
});
  • 1
    I'd love some clarification in this answer! e.g. How can I make testrpc pass 180 days? – mesqueeb Feb 22 '18 at 5:41
  • 1
    @mesqueeb There's a method in ganache called evm_increaseTime – Paul Razvan Berg Nov 12 '18 at 18:40
1

I wrote an entire article about this: Writing Accurate Time-Dependent Truffle Tests.

TLDR;

While I strongly advise to check it out (there's some subtleties involved), here's the short story.

Either do npm install ganache-time-traveler or copy-paste the following in your project:

const advanceBlockAtTime = (time) => {
  return new Promise((resolve, reject) => {
    web3.currentProvider.send(
      {
        jsonrpc: "2.0",
        method: "evm_mine",
        params: [time],
        id: new Date().getTime(),
      },
      (err, _) => {
        if (err) {
          return reject(err);
        }
        const newBlockHash = web3.eth.getBlock("latest").hash;

        return resolve(newBlockHash);
      },
    );
  });
};
1

I found a way to write time precise test by using own wrapper:

const { time } = require('openzeppelin-test-helpers');    

async function timeIncreaseTo (seconds) {
    const delay = 1000 - new Date().getMilliseconds();
    await new Promise(resolve => setTimeout(resolve, delay));
    await time.increaseTo(seconds);
}

I noticed that Ganache-cli switches EVM seconds exactly when host switches seconds. So I added waiting for new second and then increase time on EVM. So, I have 1 exact second to perform all necessary transactions and calls until EVM time will be switched.

Usage:

const { time } = require('openzeppelin-test-helpers');    

// Skip 10 sec to have exact 1 second
await timeIncreaseTo((await time.latest()).addn(10));

await this.contract.deposit(1000000);
const timeDeposited = await time.latest();

// Skip 1 year
await timeIncreaseTo(timeDeposited.add(time.duration.years(1)).subn(1));

expect(await this.contract.balanceOf(wallet)).to.be.bignumber.equal('1060000'); // +6%
await this.contract.withdrawAll();
  • 1
    This was the only solution that worked consistently for me. Everything else had issues with sometimes being off by 1 second (depending how long my test took to execute) – JasoonS Sep 26 at 3:03

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.