1

How can we increase block.number on Ganache for testing purpose ? If not possible do you know an alternative like passing X fake transactions to artificially increase block.number.

Or if we have to use a private chain: is it possible to change the time between blocks for faster testing ?

Best regards

2

You can increase block.timestamp (aka now):

web3.currentProvider.send({method: "evm_increaseTime", params: [numOfSeconds]});

Note that this method is a Ganache-extension of the standard.

So do not count on it on other node types (Geth, Parity, etc).

Also note that the code above is valid for web3.js v0.x.

You might need to run it asynchronously in web3.js v1.x.

  • Hi thanks for reply, but I need to use block.number instead of block.timestamp for security reasons. Best regards – Kevin Wad May 12 at 9:55
  • @KevinWad: Well then I guess that you'll have to execute some "dummy" transactions (e.g., add a "dummy" state variable to your contract, and call a function which increments it). – goodvibration May 12 at 10:06
  • 2
    There's evm_mine that can be used to create an empty block and you can use similarly to evm_increaseTime. – Ismael May 13 at 15:26
  • @KevinWad: See Ismael's suggestion above. – goodvibration May 13 at 15:28
  • @Ismael Thanks very much ! Goodvibration thanks for letting me know ! – Kevin Wad May 13 at 15:33
2

In addition to goodvibration's answer, OpenZeppelin recently released their openzeppelin-test-helpers package. This library contains all kinds of helpers for testing smart contracts, including methods to increase the block number or timestamp, such as:

async time.advanceBlock()
async time.increase(duration)
async time.increaseTo(target)

I haven't used the library myself, but it sounds like it might be useful for you.

  • Ok thanks you very much ! – Kevin Wad May 19 at 10:06
  • 1
    This library looks cool, but note that it breaks compatibility with BigNumber.js, due to several imports that use BN.js. For instance, in my case, all tests that had "should.be.bignumber.equal" broke. – Paul Razvan Berg Jul 24 at 21:01
  • @PaulBerg that's a very good point – Rosco Kalis Jul 24 at 21:16
2

I needed a promise-based solution that didn't require installing a third-party library. Copy-pasting from Ethan Wessel's amazing article on truffle time testing:

advanceTime = (time) => {
  return new Promise((resolve, reject) => {
    web3.currentProvider.send({
      jsonrpc: '2.0',
      method: 'evm_increaseTime',
      params: [time],
      id: new Date().getTime()
    }, (err, result) => {
      if (err) { return reject(err) }
      return resolve(result)
    })
  })
}

advanceBlock = () => {
  return new Promise((resolve, reject) => {
    web3.currentProvider.send({
      jsonrpc: '2.0',
      method: 'evm_mine',
      id: new Date().getTime()
    }, (err, result) => {
      if (err) { return reject(err) }
      const newBlockHash = web3.eth.getBlock('latest').hash

      return resolve(newBlockHash)
    })
  })
}

takeSnapshot = () => {
  return new Promise((resolve, reject) => {
    web3.currentProvider.send({
      jsonrpc: '2.0',
      method: 'evm_snapshot',
      id: new Date().getTime()
    }, (err, snapshotId) => {
      if (err) { return reject(err) }
      return resolve(snapshotId)
    })
  })
}

revertToSnapShot = (id) => {
  return new Promise((resolve, reject) => {
    web3.currentProvider.send({
      jsonrpc: '2.0',
      method: 'evm_revert',
      params: [id],
      id: new Date().getTime()
    }, (err, result) => {
      if (err) { return reject(err) }
      return resolve(result)
    })
  })
}

advanceTimeAndBlock = async (time) => {
  await advanceTime(time)
  await advanceBlock()
  return Promise.resolve(web3.eth.getBlock('latest'))
}

module.exports = {
  advanceTime,
  advanceBlock,
  advanceTimeAndBlock,
  takeSnapshot,
  revertToSnapShot
}

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.