const { ethers } = require("hardhat") let snapshots = [] async function snapshot() { const id = await ethers.provider.send("evm_snapshot") const time = await currentTime() snapshots.push({ id, time }) } async function revert() { const { id, time } = snapshots.pop() await ethers.provider.send("evm_revert", [id]) await ethers.provider.send("evm_setNextBlockTimestamp", [time + 1]) } /** * Mines new block. * * This call increases the block's timestamp by 1! * * @returns {Promise} */ async function mine() { await ethers.provider.send("evm_mine") } async function ensureMinimumBlockHeight(height) { while ((await ethers.provider.getBlockNumber()) < height) { await mine() } } async function currentTime() { let block = await ethers.provider.getBlock("latest") return block.timestamp } /** * Function that advances time by adding seconds to current timestamp for **next block**. * * If you need the timestamp to be already applied for current block then mine a new block with `mine()` after this call. * This is mainly needed when doing assertions on top of view calls that does not create transactions and mine new block. * * @param timestamp * @returns {Promise} */ async function advanceTimeForNextBlock(seconds) { await ethers.provider.send("evm_increaseTime", [seconds]) } /** * Function that sets specific timestamp for **next block**. * * If you need the timestamp to be already applied for current block then mine a new block with `mine()` after this call. * This is mainly needed when doing assertions on top of view calls that does not create transactions and mine new block. * * @param timestamp * @returns {Promise} */ async function advanceTimeToForNextBlock(timestamp) { await ethers.provider.send("evm_setNextBlockTimestamp", [timestamp]) } module.exports = { snapshot, revert, mine, ensureMinimumBlockHeight, currentTime, advanceTimeForNextBlock, advanceTimeToForNextBlock, }