Blockchain security isn't optional.
Protect your smart contracts and DeFi protocols with Three Sigma, a trusted security partner in blockchain audits, smart contract vulnerability assessments, and Web3 security.
Get a Quote Today
Introduction
In the previous episode of the series (Part 3) we mastered negative testing and event verification. Today we get to play time-lord: vm.roll
and vm.warp
let your tests hop to any block number or timestamp, perfect for deadlines, vesting schedules, and block-based locks.
Cheatcode vm.roll
, Controlling the Block Number
vm.roll(uint256 newHeight)
jumps the blockchain’s block number to newHeight
(keeping timestamp unchanged). This is useful for testing time-based or block-based logic. For example, many contracts lock functionality until a certain block or allow actions only when n blocks have passed. You can simulate that easily:

In the test, after deploying at N, you’d do:

Because Forge uses a deterministic EVM, the above call will indeed see block.number
≥ unlockBlock
, allowing the action to succeed. Conversely, if you rolled to a lesser number, it would revert.
Importantly, vm.roll
only sets the block number, while the block timestamp (block.timestamp
) remains what it was. Foundry also provides vm.warp
to set the timestamp (see next section). In combination, you often advance both number and time to simulate progression. These cheatcodes let you “push the block.timestamp
and block.number
into the future” easily. (A Foundry tutorial on a lottery contract, for instance, uses vm.warp(...)
and vm.roll(...)
back-to-back to simulate the passing of the lottery interval.)
Because block.number
is normally monotonic, vm.roll
can also be used to shrink (rewind) the block height by giving a smaller number, though care is needed since contracts may assume increasing blocks.
Advanced tip: Invariant or fuzz tests might internally use roll
to explore block-time invariants. Also, Forge’s block manipulation works seamlessly across forks, if you fork mainnet, vm.roll
still overrides the number for your test environment. Overall, vm.roll
unlocks any scenario where a certain block number condition must be met, without waiting in real-time.
Cheatcode vm.warp, Controlling the Block Timestamp
Similar to vm.roll
, vm.warp(uint256 newTime)
sets the blockchain’s current block.timestamp
to newTime
. This is essential for testing time-based logic (deadlines, vesting, interest accrual, etc.). For example, consider a time-lock:

In tests you might write:

The call to vm.warp(...)
leaps time to a point where block.timestamp >= releaseTime
, so the withdraw logic passes. If you tried calling before warp, it would revert as expected. Combining vm.warp
with vm.expectRevert
is a common pattern to test both pre- and post-deadline behavior.
Foundry also offers handy shortcuts: skip(x)
advances time by x
seconds, and rewind(x)
moves time backwards (if needed). But the core cheatcode is vm.warp
. As with roll, timestamp changes are only effective for the next transaction; the test context continues with the new time.

In real contracts, you might need to test interest that accrues over time, auction expiration, or NFT reveal deadlines. vm.warp
lets you simulate long waits instantly. Just be mindful: if your contract also depends on block number, you may need both vm.warp
and vm.roll
together (or use skip
/rewind
which affect time only). In any case, these time-travel cheats make it trivial to hit very old or future timestamps.