JavaScript testing helpers for Ethereum smart contract development with assertions, event verification, balance tracking, and time manipulation.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Blockchain time and block manipulation utilities for testing time-dependent contract behavior in development networks. Essential for testing time locks, vesting schedules, and other temporal smart contract logic.
Mine new blocks to advance the blockchain state.
/**
* Mine one block on the blockchain
* @returns {Promise<void>}
*/
function time.advanceBlock();
/**
* Advance blockchain to a specific block number
* @param {BN|number|string} target - Target block number
* @returns {Promise<void>}
*/
async function time.advanceBlockTo(target);Usage Examples:
const { time, BN } = require('@openzeppelin/test-helpers');
// Mine a single block
await time.advanceBlock();
// Advance to specific block (careful with large jumps!)
const targetBlock = await time.latestBlock().add(new BN('10'));
await time.advanceBlockTo(targetBlock);Get current blockchain time and block information.
/**
* Get the timestamp of the latest block in seconds
* @returns {Promise<BN>} - Block timestamp as BigNumber
*/
async function time.latest();
/**
* Get the latest block number
* @returns {Promise<BN>} - Block number as BigNumber
*/
async function time.latestBlock();Usage Examples:
// Get current block timestamp
const now = await time.latest();
console.log('Current time:', now.toString());
// Get current block number
const blockNumber = await time.latestBlock();
console.log('Current block:', blockNumber.toString());
// Compare timestamps
const deadline = now.add(time.duration.days(7));
expect(deadline).to.be.bignumber.greaterThan(now);Manipulate blockchain time for testing time-dependent functionality.
/**
* Increase blockchain time by a specific duration
* @param {BN|number|string} duration - Duration in seconds to increase
* @returns {Promise<void>}
*/
async function time.increase(duration);
/**
* Increase blockchain time to a specific target timestamp
* @param {BN|number|string} target - Target timestamp in seconds
* @returns {Promise<void>}
*/
async function time.increaseTo(target);Usage Examples:
const { time } = require('@openzeppelin/test-helpers');
// Increase time by 1 hour
await time.increase(time.duration.hours(1));
// Jump to specific future time
const futureTime = (await time.latest()).add(time.duration.days(30));
await time.increaseTo(futureTime);
// Test time-locked function
it('should allow withdrawal after lock period', async function () {
// Lock funds for 1 week
await this.contract.lockFunds({ from: user });
// Try to withdraw immediately (should fail)
await expectRevert(
this.contract.withdraw({ from: user }),
'Funds are still locked'
);
// Advance time by 1 week
await time.increase(time.duration.weeks(1));
// Now withdrawal should succeed
await this.contract.withdraw({ from: user });
});Convenient time duration conversion utilities.
const time.duration = {
/**
* Convert seconds to BigNumber
* @param {number|string} val - Value in seconds
* @returns {BN} - Duration as BigNumber
*/
seconds: (val) => BN,
/**
* Convert minutes to seconds as BigNumber
* @param {number|string} val - Value in minutes
* @returns {BN} - Duration in seconds as BigNumber
*/
minutes: (val) => BN,
/**
* Convert hours to seconds as BigNumber
* @param {number|string} val - Value in hours
* @returns {BN} - Duration in seconds as BigNumber
*/
hours: (val) => BN,
/**
* Convert days to seconds as BigNumber
* @param {number|string} val - Value in days
* @returns {BN} - Duration in seconds as BigNumber
*/
days: (val) => BN,
/**
* Convert weeks to seconds as BigNumber
* @param {number|string} val - Value in weeks
* @returns {BN} - Duration in seconds as BigNumber
*/
weeks: (val) => BN,
/**
* Convert years to seconds as BigNumber (365 days)
* @param {number|string} val - Value in years
* @returns {BN} - Duration in seconds as BigNumber
*/
years: (val) => BN,
};Usage Examples:
// Duration calculations
const oneHour = time.duration.hours(1);
const oneDay = time.duration.days(1);
const oneWeek = time.duration.weeks(1);
const oneYear = time.duration.years(1);
console.log('1 hour =', oneHour.toString(), 'seconds');
console.log('1 day =', oneDay.toString(), 'seconds');
console.log('1 week =', oneWeek.toString(), 'seconds');
console.log('1 year =', oneYear.toString(), 'seconds');
// Combining durations
const lockPeriod = time.duration.days(30).add(time.duration.hours(12));
await time.increase(lockPeriod);const { time, expectRevert, BN } = require('@openzeppelin/test-helpers');
contract('TimeLock', function ([owner, beneficiary]) {
beforeEach(async function () {
this.lockDuration = time.duration.days(30);
this.releaseTime = (await time.latest()).add(this.lockDuration);
this.timeLock = await TimeLock.new(
beneficiary,
this.releaseTime,
{ from: owner }
);
});
it('should not allow release before time', async function () {
await expectRevert(
this.timeLock.release(),
'TimeLock: current time is before release time'
);
});
it('should allow release after time', async function () {
// Fast forward to release time
await time.increaseTo(this.releaseTime);
// Should now be able to release
await this.timeLock.release();
});
it('should handle gradual vesting', async function () {
const vestingStart = await time.latest();
const vestingDuration = time.duration.days(100);
// Check vesting at different points
await time.increaseTo(vestingStart.add(time.duration.days(25)));
let vestedAmount = await this.vestingContract.vestedAmount(beneficiary);
expect(vestedAmount).to.be.bignumber.equal(new BN('25')); // 25% vested
await time.increaseTo(vestingStart.add(time.duration.days(50)));
vestedAmount = await this.vestingContract.vestedAmount(beneficiary);
expect(vestedAmount).to.be.bignumber.equal(new BN('50')); // 50% vested
await time.increaseTo(vestingStart.add(vestingDuration));
vestedAmount = await this.vestingContract.vestedAmount(beneficiary);
expect(vestedAmount).to.be.bignumber.equal(new BN('100')); // 100% vested
});
});The advanceBlockTo function will show a warning when advancing many blocks (5+ seconds), as this can slow down tests significantly.
Time manipulation is subject to blockchain precision limitations. Design tests to tolerate small time fluctuations when using increaseTo.
Time manipulation requires a development blockchain that supports:
evm_increaseTime RPC methodevm_mine RPC methodCompatible with:
Remember that advancing time also mines a block. Some contracts may depend on block numbers rather than timestamps.
// Advance time without mining extra blocks
await time.increase(time.duration.hours(1));
// This will mine one additional block after time increase
// Current block number = previous + 1Install with Tessl CLI
npx tessl i tessl/npm-openzeppelin--test-helpers